From d6bd53fe5ca146398e9c3547b6cd9a06cf56d90f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 25 May 2011 00:32:23 +0000 Subject: Move sanitised serialisation headers to public include directory git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3320 a436a847-0d15-0410-975c-d299462d15a1 --- include/ingen/serialisation/Parser.hpp | 87 ++++ include/ingen/serialisation/Serialiser.hpp | 83 ++++ src/client/HTTPClientReceiver.hpp | 2 +- src/gui/Configuration.cpp | 2 +- src/gui/LoadPatchWindow.cpp | 11 +- src/gui/PatchCanvas.cpp | 2 +- src/gui/PatchWindow.cpp | 11 +- src/gui/ThreadedLoader.cpp | 3 +- src/gui/ThreadedLoader.hpp | 5 +- src/gui/UploadPatchWindow.cpp | 3 +- src/ingen/main.cpp | 2 +- src/serialisation/Parser.cpp | 700 +++++++++++++++-------------- src/serialisation/Parser.hpp | 128 ------ src/serialisation/Serialiser.cpp | 167 ++++--- src/serialisation/Serialiser.hpp | 116 ----- src/serialisation/names.hpp | 24 - src/serialisation/serialisation.cpp | 4 +- src/server/HTTPClientSender.cpp | 2 +- src/server/HTTPEngineReceiver.cpp | 4 +- src/server/JackDriver.cpp | 2 +- src/server/ingen_lv2.cpp | 2 +- 21 files changed, 686 insertions(+), 674 deletions(-) create mode 100644 include/ingen/serialisation/Parser.hpp create mode 100644 include/ingen/serialisation/Serialiser.hpp delete mode 100644 src/serialisation/Parser.hpp delete mode 100644 src/serialisation/Serialiser.hpp delete mode 100644 src/serialisation/names.hpp diff --git a/include/ingen/serialisation/Parser.hpp b/include/ingen/serialisation/Parser.hpp new file mode 100644 index 00000000..3f7bcb35 --- /dev/null +++ b/include/ingen/serialisation/Parser.hpp @@ -0,0 +1,87 @@ +/* This file is part of Ingen. + * Copyright 2007-2011 David Robillard + * + * Ingen 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. + * + * Ingen 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 INGEN_SERIALISATION_PARSER_HPP +#define INGEN_SERIALISATION_PARSER_HPP + +#include +#include + +#include +#include + +#include "raul/Path.hpp" +#include "serd/serd.h" + +#include "ingen/GraphObject.hpp" + +namespace Ingen { + +class CommonInterface; + +namespace Shared { class World; } + +namespace Serialisation { + +/** Parse Ingen objects from RDF. + * + * \ingroup IngenSerialisation + */ +class Parser { +public: + Parser(Shared::World& world); + + virtual ~Parser() {} + + typedef GraphObject::Properties Properties; + + virtual bool parse_file( + Shared::World* world, + CommonInterface* target, + Glib::ustring document_uri, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + + virtual bool parse_string( + Shared::World* world, + CommonInterface* target, + const Glib::ustring& str, + const Glib::ustring& base_uri, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + + struct PatchRecord { + PatchRecord(const Raul::URI& u, const Glib::ustring& f) + : patch_uri(u), file_uri(f) + {} + const Raul::URI patch_uri; + const Glib::ustring file_uri; + }; + + typedef std::list PatchRecords; + + virtual PatchRecords find_patches(Shared::World* world, + SerdEnv* env, + const Glib::ustring& manifest_uri); +}; + +} // namespace Serialisation +} // namespace Ingen + +#endif // INGEN_SERIALISATION_PARSER_HPP diff --git a/include/ingen/serialisation/Serialiser.hpp b/include/ingen/serialisation/Serialiser.hpp new file mode 100644 index 00000000..b4e7015b --- /dev/null +++ b/include/ingen/serialisation/Serialiser.hpp @@ -0,0 +1,83 @@ +/* This file is part of Ingen. + * Copyright 2007-2011 David Robillard + * + * Ingen 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. + * + * Ingen 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 INGEN_SERIALISATION_SERIALISER_HPP +#define INGEN_SERIALISATION_SERIALISER_HPP + +#include +#include + +#include "raul/Path.hpp" +#include "raul/SharedPtr.hpp" + +#include "sord/sordmm.hpp" + +#include "ingen/GraphObject.hpp" + +namespace Ingen { + +class Plugin; +class GraphObject; +class Patch; +class Node; +class Port; +class Connection; + +namespace Shared { class World; class Store; } + +namespace Serialisation { + +/** Serialises Ingen objects (patches, nodes, etc) to RDF. + * + * \ingroup IngenSerialisation + */ +class Serialiser +{ +public: + Serialiser(Shared::World& world, SharedPtr store); + + typedef GraphObject::Properties Properties; + + void to_file(SharedPtr object, + const std::string& filename); + + void write_bundle(SharedPtr patch, + const std::string& uri); + + std::string to_string(SharedPtr object, + const std::string& base_uri, + const Properties& extra_rdf); + + void start_to_string(const Raul::Path& root, + const std::string& base_uri); + + void serialise(SharedPtr object) throw (std::logic_error); + + void serialise_connection(const Sord::Node& parent, + SharedPtr c) throw (std::logic_error); + + std::string finish(); + +private: + struct Impl; + Impl* me; +}; + +} // namespace Serialisation +} // namespace Ingen + +#endif // INGEN_SERIALISATION_SERIALISER_HPP diff --git a/src/client/HTTPClientReceiver.hpp b/src/client/HTTPClientReceiver.hpp index 2ad1ab19..8bc4803a 100644 --- a/src/client/HTTPClientReceiver.hpp +++ b/src/client/HTTPClientReceiver.hpp @@ -26,7 +26,7 @@ #include "raul/SharedPtr.hpp" #include "raul/Thread.hpp" #include "ingen/ClientInterface.hpp" -#include "serialisation/Parser.hpp" +#include "ingen/serialisation/Parser.hpp" typedef struct _SoupSession SoupSession; typedef struct _SoupMessage SoupMessage; diff --git a/src/gui/Configuration.cpp b/src/gui/Configuration.cpp index f0e9a6ad..8eb39cd7 100644 --- a/src/gui/Configuration.cpp +++ b/src/gui/Configuration.cpp @@ -23,7 +23,7 @@ #include "raul/log.hpp" #include "ingen/client/PortModel.hpp" #include "ingen/client/PluginModel.hpp" -#include "serialisation/Parser.hpp" +#include "ingen/serialisation/Parser.hpp" #include "shared/LV2URIMap.hpp" #include "flowcanvas/Port.hpp" #include "App.hpp" diff --git a/src/gui/LoadPatchWindow.cpp b/src/gui/LoadPatchWindow.cpp index c15512a9..1d4cb7c8 100644 --- a/src/gui/LoadPatchWindow.cpp +++ b/src/gui/LoadPatchWindow.cpp @@ -26,7 +26,6 @@ #include "ingen/client/PatchModel.hpp" #include "ingen/client/ClientStore.hpp" #include "shared/runtime_paths.hpp" -#include "serialisation/names.hpp" #include "App.hpp" #include "LoadPatchWindow.hpp" #include "PatchView.hpp" @@ -75,12 +74,10 @@ LoadPatchWindow::LoadPatchWindow(BaseObjectType* cobject, sigc::mem_fun(this, &LoadPatchWindow::selection_changed)); Gtk::FileFilter filt; - filt.add_pattern("*" INGEN_PATCH_FILE_EXT); - filt.set_name("Ingen patch files (*" INGEN_PATCH_FILE_EXT ")"); - filt.add_pattern("*" INGEN_BUNDLE_EXT); - filt.set_name("Ingen bundles (*" INGEN_BUNDLE_EXT ")"); - filt.add_pattern("*.om"); - filt.set_name("Om patch files (*.om)"); + filt.add_pattern("*.ttl"); + filt.set_name("Ingen patch files (*.ttl)"); + filt.add_pattern("*.ingen"); + filt.set_name("Ingen bundles (*.ingen)"); set_filter(filt); diff --git a/src/gui/PatchCanvas.cpp b/src/gui/PatchCanvas.cpp index 6cf461e7..70efb855 100644 --- a/src/gui/PatchCanvas.cpp +++ b/src/gui/PatchCanvas.cpp @@ -26,7 +26,7 @@ #include "shared/LV2URIMap.hpp" #include "shared/Builder.hpp" #include "shared/ClashAvoider.hpp" -#include "serialisation/Serialiser.hpp" +#include "ingen/serialisation/Serialiser.hpp" #include "ingen/client/PluginModel.hpp" #include "ingen/client/PatchModel.hpp" #include "ingen/client/NodeModel.hpp" diff --git a/src/gui/PatchWindow.cpp b/src/gui/PatchWindow.cpp index 657d2874..b06c3fb5 100644 --- a/src/gui/PatchWindow.cpp +++ b/src/gui/PatchWindow.cpp @@ -26,7 +26,6 @@ #include "shared/LV2URIMap.hpp" #include "ingen/client/PatchModel.hpp" #include "ingen/client/ClientStore.hpp" -#include "serialisation/names.hpp" #include "App.hpp" #include "PatchCanvas.hpp" #include "LoadPluginWindow.hpp" @@ -425,7 +424,7 @@ PatchWindow::event_save_as() save_button->property_has_default() = true; Gtk::FileFilter filt; - filt.add_pattern("*" INGEN_BUNDLE_EXT); + filt.add_pattern("*.ingen"); filt.set_name("Ingen bundles"); dialog.set_filter(filt); @@ -443,11 +442,11 @@ PatchWindow::event_save_as() std::string basename = Glib::path_get_basename(filename); if (basename.find('.') == string::npos) { - filename += INGEN_BUNDLE_EXT; - basename += INGEN_BUNDLE_EXT; - } else if (filename.substr(filename.length() - 10) != INGEN_BUNDLE_EXT) { + filename += ".ingen"; + basename += ".ingen"; + } else if (filename.substr(filename.length() - 10) != ".ingen") { Gtk::MessageDialog error_dialog(*this, -"" "Ingen patches must be saved to Ingen bundles (*" INGEN_BUNDLE_EXT ")." "", +"" "Ingen patches must be saved to Ingen bundles (*.ingen)." "", true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); error_dialog.run(); continue; diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp index 3cba5f97..e4dbb303 100644 --- a/src/gui/ThreadedLoader.cpp +++ b/src/gui/ThreadedLoader.cpp @@ -19,7 +19,6 @@ #include "raul/log.hpp" #include "shared/World.hpp" #include "shared/Module.hpp" -#include "serialisation/names.hpp" #include "App.hpp" #include "ThreadedLoader.hpp" #include "ingen/client/PatchModel.hpp" @@ -120,7 +119,7 @@ ThreadedLoader::save_patch_event(SharedPtr model, const string& filename) { if (App::instance().serialiser()) { - if (filename.find(INGEN_BUNDLE_EXT) != string::npos) + if (filename.find(".ingen") != string::npos) App::instance().serialiser()->write_bundle(model, filename); else App::instance().serialiser()->to_file(model, filename); diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index 41f56340..ab5995f9 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -26,8 +26,9 @@ #include "raul/Slave.hpp" #include #include "ingen/ServerInterface.hpp" -#include "serialisation/Serialiser.hpp" -#include "serialisation/Parser.hpp" +#include "ingen/serialisation/Serialiser.hpp" +#include "ingen/serialisation/Parser.hpp" + using std::string; using std::list; using boost::optional; diff --git a/src/gui/UploadPatchWindow.cpp b/src/gui/UploadPatchWindow.cpp index 9bf4ec52..0c02f411 100644 --- a/src/gui/UploadPatchWindow.cpp +++ b/src/gui/UploadPatchWindow.cpp @@ -25,8 +25,7 @@ #include "shared/LV2URIMap.hpp" #include "ingen/client/ClientStore.hpp" #include "ingen/ServerInterface.hpp" -#include "serialisation/Serialiser.hpp" -#include "serialisation/names.hpp" +#include "ingen/serialisation/Serialiser.hpp" #include "ingen/client/PatchModel.hpp" #include "UploadPatchWindow.hpp" #include "App.hpp" diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp index 48f445a3..2910f9eb 100644 --- a/src/ingen/main.cpp +++ b/src/ingen/main.cpp @@ -41,7 +41,7 @@ #include "ingen/EngineBase.hpp" #include "ingen/ServerInterface.hpp" -#include "serialisation/Parser.hpp" +#include "ingen/serialisation/Parser.hpp" #include "shared/Configuration.hpp" #include "shared/World.hpp" #include "shared/runtime_paths.hpp" diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index 198a520e..27110c9d 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -38,8 +38,7 @@ #include "shared/World.hpp" #include "shared/LV2URIMap.hpp" -#include "Parser.hpp" -#include "names.hpp" +#include "ingen/serialisation/Parser.hpp" #define LOG(s) s << "[Parser] " @@ -102,226 +101,6 @@ skip_property(const Sord::Node& predicate) || predicate.to_string() == "http://lv2plug.in/ns/lv2core#port"); } -Parser::Parser(Ingen::Shared::World& world) -{ -} - -Parser::PatchRecords -Parser::find_patches(Ingen::Shared::World* world, - SerdEnv* env, - const Glib::ustring& manifest_uri) -{ - const Sord::URI ingen_Patch (*world->rdf_world(), NS_INGEN "Patch"); - const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type"); - const Sord::URI rdfs_seeAlso(*world->rdf_world(), NS_RDFS "seeAlso"); - - Sord::Model model(*world->rdf_world(), manifest_uri); - model.load_file(env, SERD_TURTLE, manifest_uri); - - std::list records; - for (Sord::Iter i = model.find(nil, rdf_type, ingen_Patch); !i.end(); ++i) { - const Sord::Node patch = i.get_subject(); - Sord::Iter f = model.find(patch, rdfs_seeAlso, nil); - if (!f.end()) { - records.push_back(PatchRecord(patch.to_c_string(), - f.get_object().to_c_string())); - } else { - LOG(error) << "Patch has no rdfs:seeAlso" << endl; - } - } - return records; -} - -/** Parse a patch from RDF into a CommonInterface (engine or client). - * @return whether or not load was successful. - */ -bool -Parser::parse_file(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Glib::ustring file_uri, - boost::optional parent, - boost::optional symbol, - boost::optional data) -{ - const size_t colon = file_uri.find(":"); - if (colon != Glib::ustring::npos) { - const Glib::ustring scheme = file_uri.substr(0, colon); - if (scheme != "file") { - LOG(error) << (boost::format("Unsupported URI scheme `%1%'") - % scheme) << endl; - return false; - } - } else { - file_uri = Glib::ustring("file://") + file_uri; - } - - const bool is_bundle = (file_uri.substr(file_uri.length() - 4) != ".ttl"); - - if (is_bundle && file_uri[file_uri.length() - 1] != '/') { - file_uri.append("/"); - } - - SerdNode base_node = serd_node_from_string( - SERD_URI, (const uint8_t*)file_uri.c_str()); - SerdEnv* env = serd_env_new(&base_node); - - if (file_uri.substr(file_uri.length() - 4) != ".ttl") { - // Not a Turtle file, try to open it as a bundle - if (file_uri[file_uri.length() - 1] != '/') { - file_uri.append("/"); - } - Parser::PatchRecords records = find_patches(world, env, file_uri + "manifest.ttl"); - if (!records.empty()) { - file_uri = records.front().file_uri; - } - } - - base_node = serd_node_from_string( - SERD_URI, (const uint8_t*)file_uri.c_str()); - serd_env_set_base_uri(env, &base_node); - - // Load patch file into model - Sord::Model model(*world->rdf_world(), file_uri); - model.load_file(env, SERD_TURTLE, file_uri); - - serd_env_free(env); - - LOG(info) << "Parsing " << file_uri << endl; - if (parent) - LOG(info) << "Parent: " << *parent << endl; - if (symbol) - LOG(info) << "Symbol: " << *symbol << endl; - - boost::optional parsed_path - = parse(world, target, model, file_uri, Path("/"), parent, symbol, data); - - if (parsed_path) { - target->set_property(*parsed_path, "http://drobilla.net/ns/ingen#document", - Atom(Atom::URI, file_uri.c_str())); - } else { - LOG(warn) << "Document URI lost" << endl; - } - - return parsed_path; -} - -bool -Parser::parse_string(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - const Glib::ustring& str, - const Glib::ustring& base_uri, - boost::optional parent, - boost::optional symbol, - boost::optional data) -{ - // Load string into model - Sord::Model model(*world->rdf_world(), base_uri); - SerdEnv* env = serd_env_new(NULL); - model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); - serd_env_free(env); - - LOG(info) << "Parsing string"; - if (!base_uri.empty()) - info << " (base " << base_uri << ")"; - info << endl; - - boost::optional data_path; - bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data); - Sord::URI subject(*world->rdf_world(), base_uri); - parse_connections(world, target, model, subject, parent ? *parent : "/"); - - return ret; -} - -boost::optional -Parser::parse(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - Glib::ustring document_uri, - boost::optional data_path, - boost::optional parent, - boost::optional symbol, - boost::optional data) -{ - const Sord::URI patch_class (*world->rdf_world(), NS_INGEN "Patch"); - const Sord::URI node_class (*world->rdf_world(), NS_INGEN "Node"); - const Sord::URI port_class (*world->rdf_world(), NS_INGEN "Port"); - const Sord::URI internal_class(*world->rdf_world(), NS_INGEN "Internal"); - const Sord::URI in_port_class (*world->rdf_world(), NS_LV2 "InputPort"); - const Sord::URI out_port_class(*world->rdf_world(), NS_LV2 "OutputPort"); - const Sord::URI lv2_class (*world->rdf_world(), NS_LV2 "Plugin"); - const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type"); - - Sord::Node subject = nil; - if (data_path && data_path->is_root()) { - subject = model.base_uri(); - } else if (data_path) { - subject = Sord::URI(*world->rdf_world(), data_path->chop_start("/")); - } - - Raul::Path path("/"); - if (data_path) { - path = *data_path; - } else if (parent && symbol) { - path = parent->child(*symbol); - } - - // Get all subjects and their types (?subject a ?type) - typedef std::map< Sord::Node, std::set > Subjects; - Subjects subjects; - for (Sord::Iter i = model.find(subject, rdf_type, nil); !i.end(); ++i) { - const Sord::Node& subject = i.get_subject(); - const Sord::Node& rdf_class = i.get_object(); - - assert(rdf_class.is_uri()); - Subjects::iterator s = subjects.find(subject); - if (s == subjects.end()) { - std::set types; - types.insert(rdf_class); - subjects.insert(make_pair(subject, types)); - } else { - s->second.insert(rdf_class); - } - } - - // Parse and create each subject - boost::optional ret; - boost::optional root_path; - for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) { - const Sord::Node& subject = i->first; - const std::set& types = i->second; - if (types.find(patch_class) != types.end()) { - ret = parse_patch(world, target, model, subject, parent, symbol, data); - } else if (types.find(node_class) != types.end()) { - ret = parse_node(world, target, model, - subject, path.child(subject.to_string()), - data); - } else if (types.find(port_class) != types.end()) { - parse_properties(world, target, model, subject, path, data); - ret = path; - } else { - LOG(error) << "Subject has no known types" << endl; - } - - if (!ret) { - LOG(error) << "Failed to parse " << path << endl; - LOG(error) << "Types:" << endl; - for (std::set::const_iterator t = types.begin(); - t != types.end(); ++t) { - LOG(error) << " :: " << *t << endl; - assert((*t).is_uri()); - } - return boost::optional(); - } - - if (data_path && subject.to_string() == data_path->str()) { - root_path = ret; - } - } - - return path; -} - static Resource::Properties get_properties(Sord::Model& model, const Sord::Node& subject) @@ -376,14 +155,122 @@ get_port(Ingen::Shared::World* world, return index; } -boost::optional -Parser::parse_patch(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject_node, - boost::optional parent, - boost::optional a_symbol, - boost::optional data) +static boost::optional +parse( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + Glib::ustring document_uri, + boost::optional data_path = boost::optional(), + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + +static boost::optional +parse_patch( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + + +static boost::optional +parse_node( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& path, + boost::optional data = boost::optional()); + + +static bool +parse_properties( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::URI& uri, + boost::optional data = boost::optional()); + +static bool +parse_connections( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& patch); + +static boost::optional +parse_node(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& path, + boost::optional data) +{ + const LV2URIMap& uris = *world->uris().get(); + + Sord::URI rdf_instanceOf(*world->rdf_world(), NS_RDF "instanceOf"); + + Sord::Iter i = model.find(subject, rdf_instanceOf, nil); + if (i.end() || i.get_object().type() != Sord::Node::URI) { + LOG(error) << "Node missing mandatory rdf:instanceOf" << endl; + return boost::optional(); + } + + const std::string type_uri = relative_uri( + model.base_uri().to_string(), + i.get_object().to_string(), + false); + + if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) { + SerdURI base_uri; + serd_uri_parse(model.base_uri().to_u_string(), &base_uri); + + SerdURI ignored; + SerdNode sub_uri = serd_node_new_uri_from_string( + i.get_object().to_u_string(), + &base_uri, + &ignored); + + const std::string sub_uri_str((const char*)sub_uri.buf); + std::string basename = get_basename(sub_uri_str); + + const std::string sub_file = + string((const char*)sub_uri.buf) + "/" + basename + ".ttl"; + + Sord::Model sub_model(*world->rdf_world(), sub_file); + SerdEnv* env = serd_env_new(NULL); + sub_model.load_file(env, SERD_TURTLE, sub_file); + serd_env_free(env); + + Sord::URI sub_node(*world->rdf_world(), sub_file); + parse_patch(world, target, sub_model, sub_node, + path.parent(), Raul::Symbol(path.symbol())); + + parse_patch(world, target, model, subject, + path.parent(), Raul::Symbol(path.symbol())); + } else { + Resource::Properties props = get_properties(model, subject); + props.insert(make_pair(uris.rdf_type, + Raul::URI(uris.ingen_Node))); + target->put(path, props); + } + return path; +} + +static boost::optional +parse_patch(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject_node, + boost::optional parent, + boost::optional a_symbol, + boost::optional data) { const Sord::URI ingen_node(*world->rdf_world(), NS_INGEN "node"); const Sord::URI ingen_polyphony(*world->rdf_world(), NS_INGEN "polyphony"); @@ -463,102 +350,43 @@ Parser::parse_patch(Ingen::Shared::World* world, // Create port and/or set all port properties target->put(port_record.first, port_record.second); - } - } - - // For each port on this patch - typedef std::map PortRecords; - PortRecords ports; - for (Sord::Iter p = model.find(patch, lv2_port, nil); !p.end(); ++p) { - Sord::Node port = p.get_object(); - - // Get all properties - PortRecord port_record; - const int index = get_port(world, model, port, patch_path, port_record); - if (index < 0) { - LOG(error) << "Invalid port " << port << endl; - return boost::optional(); - } - - // Store port information in ports map - ports[index] = port_record; - } - - // Create ports in order by index - for (PortRecords::const_iterator i = ports.begin(); i != ports.end(); ++i) { - target->put(i->second.first, i->second.second); - } - - parse_connections(world, target, model, subject_node, patch_path); - - return patch_path; -} - -boost::optional -Parser::parse_node(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& path, - boost::optional data) -{ - const LV2URIMap& uris = *world->uris().get(); - - Sord::URI rdf_instanceOf(*world->rdf_world(), NS_RDF "instanceOf"); - - Sord::Iter i = model.find(subject, rdf_instanceOf, nil); - if (i.end() || i.get_object().type() != Sord::Node::URI) { - LOG(error) << "Node missing mandatory rdf:instanceOf" << endl; - return boost::optional(); - } - - const std::string type_uri = relative_uri( - model.base_uri().to_string(), - i.get_object().to_string(), - false); - - if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) { - SerdURI base_uri; - serd_uri_parse(model.base_uri().to_u_string(), &base_uri); - - SerdURI ignored; - SerdNode sub_uri = serd_node_new_uri_from_string( - i.get_object().to_u_string(), - &base_uri, - &ignored); - - const std::string sub_uri_str((const char*)sub_uri.buf); - std::string basename = get_basename(sub_uri_str); + } + } - const std::string sub_file = - string((const char*)sub_uri.buf) + "/" + basename + ".ttl"; + // For each port on this patch + typedef std::map PortRecords; + PortRecords ports; + for (Sord::Iter p = model.find(patch, lv2_port, nil); !p.end(); ++p) { + Sord::Node port = p.get_object(); - Sord::Model sub_model(*world->rdf_world(), sub_file); - SerdEnv* env = serd_env_new(NULL); - sub_model.load_file(env, SERD_TURTLE, sub_file); - serd_env_free(env); + // Get all properties + PortRecord port_record; + const int index = get_port(world, model, port, patch_path, port_record); + if (index < 0) { + LOG(error) << "Invalid port " << port << endl; + return boost::optional(); + } - Sord::URI sub_node(*world->rdf_world(), sub_file); - parse_patch(world, target, sub_model, sub_node, - path.parent(), Raul::Symbol(path.symbol())); + // Store port information in ports map + ports[index] = port_record; + } - parse_patch(world, target, model, subject, - path.parent(), Raul::Symbol(path.symbol())); - } else { - Resource::Properties props = get_properties(model, subject); - props.insert(make_pair(uris.rdf_type, - Raul::URI(uris.ingen_Node))); - target->put(path, props); + // Create ports in order by index + for (PortRecords::const_iterator i = ports.begin(); i != ports.end(); ++i) { + target->put(i->second.first, i->second.second); } - return path; + + parse_connections(world, target, model, subject_node, patch_path); + + return patch_path; } -bool -Parser::parse_connections(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& parent) +static bool +parse_connections(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& parent) { Sord::URI ingen_connection(*world->rdf_world(), NS_INGEN "connection"); Sord::URI ingen_source(*world->rdf_world(), NS_INGEN "source"); @@ -602,13 +430,13 @@ Parser::parse_connections(Ingen::Shared::World* world, return true; } -bool -Parser::parse_properties(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::URI& uri, - boost::optional data) +static bool +parse_properties(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::URI& uri, + boost::optional data) { Resource::Properties properties; for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { @@ -629,6 +457,226 @@ Parser::parse_properties(Ingen::Shared::World* world, return true; } +static boost::optional +parse(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + Glib::ustring document_uri, + boost::optional data_path, + boost::optional parent, + boost::optional symbol, + boost::optional data) +{ + const Sord::URI patch_class (*world->rdf_world(), NS_INGEN "Patch"); + const Sord::URI node_class (*world->rdf_world(), NS_INGEN "Node"); + const Sord::URI port_class (*world->rdf_world(), NS_INGEN "Port"); + const Sord::URI internal_class(*world->rdf_world(), NS_INGEN "Internal"); + const Sord::URI in_port_class (*world->rdf_world(), NS_LV2 "InputPort"); + const Sord::URI out_port_class(*world->rdf_world(), NS_LV2 "OutputPort"); + const Sord::URI lv2_class (*world->rdf_world(), NS_LV2 "Plugin"); + const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type"); + + Sord::Node subject = nil; + if (data_path && data_path->is_root()) { + subject = model.base_uri(); + } else if (data_path) { + subject = Sord::URI(*world->rdf_world(), data_path->chop_start("/")); + } + + Raul::Path path("/"); + if (data_path) { + path = *data_path; + } else if (parent && symbol) { + path = parent->child(*symbol); + } + + // Get all subjects and their types (?subject a ?type) + typedef std::map< Sord::Node, std::set > Subjects; + Subjects subjects; + for (Sord::Iter i = model.find(subject, rdf_type, nil); !i.end(); ++i) { + const Sord::Node& subject = i.get_subject(); + const Sord::Node& rdf_class = i.get_object(); + + assert(rdf_class.is_uri()); + Subjects::iterator s = subjects.find(subject); + if (s == subjects.end()) { + std::set types; + types.insert(rdf_class); + subjects.insert(make_pair(subject, types)); + } else { + s->second.insert(rdf_class); + } + } + + // Parse and create each subject + boost::optional ret; + boost::optional root_path; + for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) { + const Sord::Node& subject = i->first; + const std::set& types = i->second; + if (types.find(patch_class) != types.end()) { + ret = parse_patch(world, target, model, subject, parent, symbol, data); + } else if (types.find(node_class) != types.end()) { + ret = parse_node(world, target, model, + subject, path.child(subject.to_string()), + data); + } else if (types.find(port_class) != types.end()) { + parse_properties(world, target, model, subject, path, data); + ret = path; + } else { + LOG(error) << "Subject has no known types" << endl; + } + + if (!ret) { + LOG(error) << "Failed to parse " << path << endl; + LOG(error) << "Types:" << endl; + for (std::set::const_iterator t = types.begin(); + t != types.end(); ++t) { + LOG(error) << " :: " << *t << endl; + assert((*t).is_uri()); + } + return boost::optional(); + } + + if (data_path && subject.to_string() == data_path->str()) { + root_path = ret; + } + } + + return path; +} + +Parser::Parser(Ingen::Shared::World& world) +{ +} + +Parser::PatchRecords +Parser::find_patches(Ingen::Shared::World* world, + SerdEnv* env, + const Glib::ustring& manifest_uri) +{ + const Sord::URI ingen_Patch (*world->rdf_world(), NS_INGEN "Patch"); + const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type"); + const Sord::URI rdfs_seeAlso(*world->rdf_world(), NS_RDFS "seeAlso"); + + Sord::Model model(*world->rdf_world(), manifest_uri); + model.load_file(env, SERD_TURTLE, manifest_uri); + + std::list records; + for (Sord::Iter i = model.find(nil, rdf_type, ingen_Patch); !i.end(); ++i) { + const Sord::Node patch = i.get_subject(); + Sord::Iter f = model.find(patch, rdfs_seeAlso, nil); + if (!f.end()) { + records.push_back(PatchRecord(patch.to_c_string(), + f.get_object().to_c_string())); + } else { + LOG(error) << "Patch has no rdfs:seeAlso" << endl; + } + } + return records; +} + +/** Parse a patch from RDF into a CommonInterface (engine or client). + * @return whether or not load was successful. + */ +bool +Parser::parse_file(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Glib::ustring file_uri, + boost::optional parent, + boost::optional symbol, + boost::optional data) +{ + const size_t colon = file_uri.find(":"); + if (colon != Glib::ustring::npos) { + const Glib::ustring scheme = file_uri.substr(0, colon); + if (scheme != "file") { + LOG(error) << (boost::format("Unsupported URI scheme `%1%'") + % scheme) << endl; + return false; + } + } else { + file_uri = Glib::ustring("file://") + file_uri; + } + + const bool is_bundle = (file_uri.substr(file_uri.length() - 4) != ".ttl"); + + if (is_bundle && file_uri[file_uri.length() - 1] != '/') { + file_uri.append("/"); + } + + SerdNode base_node = serd_node_from_string( + SERD_URI, (const uint8_t*)file_uri.c_str()); + SerdEnv* env = serd_env_new(&base_node); + + if (file_uri.substr(file_uri.length() - 4) != ".ttl") { + // Not a Turtle file, try to open it as a bundle + if (file_uri[file_uri.length() - 1] != '/') { + file_uri.append("/"); + } + Parser::PatchRecords records = find_patches(world, env, file_uri + "manifest.ttl"); + if (!records.empty()) { + file_uri = records.front().file_uri; + } + } + + base_node = serd_node_from_string( + SERD_URI, (const uint8_t*)file_uri.c_str()); + serd_env_set_base_uri(env, &base_node); + + // Load patch file into model + Sord::Model model(*world->rdf_world(), file_uri); + model.load_file(env, SERD_TURTLE, file_uri); + + serd_env_free(env); + + LOG(info) << "Parsing " << file_uri << endl; + if (parent) + LOG(info) << "Parent: " << *parent << endl; + if (symbol) + LOG(info) << "Symbol: " << *symbol << endl; + + boost::optional parsed_path + = parse(world, target, model, file_uri, Path("/"), parent, symbol, data); + + if (parsed_path) { + target->set_property(*parsed_path, "http://drobilla.net/ns/ingen#document", + Atom(Atom::URI, file_uri.c_str())); + } else { + LOG(warn) << "Document URI lost" << endl; + } + + return parsed_path; +} + +bool +Parser::parse_string(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + const Glib::ustring& str, + const Glib::ustring& base_uri, + boost::optional parent, + boost::optional symbol, + boost::optional data) +{ + // Load string into model + Sord::Model model(*world->rdf_world(), base_uri); + SerdEnv* env = serd_env_new(NULL); + model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); + serd_env_free(env); + + LOG(info) << "Parsing string"; + if (!base_uri.empty()) + info << " (base " << base_uri << ")"; + info << endl; + + boost::optional data_path; + bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data); + Sord::URI subject(*world->rdf_world(), base_uri); + parse_connections(world, target, model, subject, parent ? *parent : "/"); + + return ret; +} + } // namespace Serialisation } // namespace Ingen diff --git a/src/serialisation/Parser.hpp b/src/serialisation/Parser.hpp deleted file mode 100644 index 30c04bab..00000000 --- a/src/serialisation/Parser.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard - * - * Ingen 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. - * - * Ingen 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 INGEN_SERIALISATION_PARSER_HPP -#define INGEN_SERIALISATION_PARSER_HPP - -#include -#include - -#include -#include - -#include "raul/Path.hpp" -#include "serd/serd.h" - -#include "ingen/GraphObject.hpp" - -namespace Sord { class World; class Model; class Node; } - -namespace Ingen { - -class CommonInterface; - -namespace Shared { class World; } - -namespace Serialisation { - -class Parser { -public: - Parser(Shared::World& world); - - virtual ~Parser() {} - - typedef GraphObject::Properties Properties; - - virtual bool parse_file( - Shared::World* world, - CommonInterface* target, - Glib::ustring document_uri, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - - virtual bool parse_string( - Shared::World* world, - CommonInterface* target, - const Glib::ustring& str, - const Glib::ustring& base_uri, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - - struct PatchRecord { - PatchRecord(const Raul::URI& u, const Glib::ustring& f) - : patch_uri(u), file_uri(f) - {} - const Raul::URI patch_uri; - const Glib::ustring file_uri; - }; - - typedef std::list PatchRecords; - - virtual PatchRecords find_patches(Shared::World* world, - SerdEnv* env, - const Glib::ustring& manifest_uri); - -private: - boost::optional parse( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - Glib::ustring document_uri, - boost::optional data_path = boost::optional(), - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - - boost::optional parse_patch( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - - boost::optional parse_node( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& path, - boost::optional data = boost::optional()); - - bool parse_properties( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::URI& uri, - boost::optional data = boost::optional()); - - bool parse_connections( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& patch); -}; - -} // namespace Serialisation -} // namespace Ingen - -#endif // INGEN_SERIALISATION_PARSER_HPP diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp index 253791d2..ae1a6416 100644 --- a/src/serialisation/Serialiser.cpp +++ b/src/serialisation/Serialiser.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -49,12 +50,12 @@ #include "ingen/Patch.hpp" #include "ingen/Plugin.hpp" #include "ingen/Port.hpp" -#include "shared/World.hpp" #include "shared/LV2URIMap.hpp" #include "shared/ResourceImpl.hpp" +#include "shared/Store.hpp" +#include "shared/World.hpp" -#include "Serialiser.hpp" -#include "names.hpp" +#include "ingen/serialisation/Serialiser.hpp" #define LOG(s) s << "[Serialiser] " @@ -69,19 +70,66 @@ using namespace Ingen::Shared; namespace Ingen { namespace Serialisation { +struct Serialiser::Impl { + Impl(Shared::World& world, SharedPtr store) + : _root_path("/") + , _store(store) + , _world(world) + {} + + enum Mode { TO_FILE, TO_STRING }; + + void start_to_filename(const std::string& filename); + + void serialise_patch(SharedPtr p, + const Sord::Node& id); + + void serialise_node(SharedPtr n, + const Sord::Node& class_id, + const Sord::Node& id); + + void serialise_port(const Port* p, + Resource::Graph context, + const Sord::Node& id); + + void serialise_properties(const GraphObject* o, + Resource::Graph context, + Sord::Node id); + + void write_bundle(SharedPtr patch, + const std::string& uri); + + Sord::Node path_rdf_node(const Raul::Path& path); + + void write_manifest(const std::string& bundle_path, + SharedPtr patch, + const std::string& patch_symbol); + + void serialise_connection(const Sord::Node& parent, + SharedPtr c) + throw (std::logic_error); + + std::string finish(); + + Raul::Path _root_path; + SharedPtr _store; + Mode _mode; + std::string _base_uri; + Shared::World& _world; + Sord::Model* _model; +}; + + Serialiser::Serialiser(Shared::World& world, SharedPtr store) - : _root_path("/") - , _store(store) - , _world(world) -{ -} + : me(new Impl(world, store)) +{} void Serialiser::to_file(SharedPtr object, const std::string& filename) { - _root_path = object->path(); - start_to_filename(filename); + me->_root_path = object->path(); + me->start_to_filename(filename); serialise(object); finish(); } @@ -96,9 +144,9 @@ uri_to_symbol(const std::string& uri) } void -Serialiser::write_manifest(const std::string& bundle_path, - SharedPtr patch, - const std::string& patch_symbol) +Serialiser::Impl::write_manifest(const std::string& bundle_path, + SharedPtr patch, + const std::string& patch_symbol) { const string manifest_path(Glib::build_filename(bundle_path, "manifest.ttl")); const string binary_path(Glib::Module::build_path("", "ingen_lv2")); @@ -107,7 +155,7 @@ Serialiser::write_manifest(const std::string& bundle_path, Sord::World& world = _model->world(); - const string filename(patch_symbol + INGEN_PATCH_FILE_EXT); + const string filename(patch_symbol + ".ttl"); const Sord::URI subject(world, filename); _model->add_statement(subject, @@ -149,6 +197,13 @@ normal_bundle_uri(const std::string& uri) void Serialiser::write_bundle(SharedPtr patch, const std::string& uri) +{ + me->write_bundle(patch, uri); +} + +void +Serialiser::Impl::write_bundle(SharedPtr patch, + const std::string& uri) { Glib::ustring path = ""; try { @@ -169,7 +224,7 @@ Serialiser::write_bundle(SharedPtr patch, g_mkdir_with_parents(path.c_str(), 0744); const string symbol = uri_to_symbol(uri); - const string root_file = path + symbol + INGEN_PATCH_FILE_EXT; + const string root_file = path + symbol + ".ttl"; start_to_filename(root_file); const Path old_root_path = _root_path; @@ -189,12 +244,12 @@ Serialiser::to_string(SharedPtr object, start_to_string(object->path(), base_uri); serialise(object); - Sord::URI base_rdf_node(_model->world(), base_uri); + Sord::URI base_rdf_node(me->_model->world(), base_uri); for (GraphObject::Properties::const_iterator v = extra_rdf.begin(); v != extra_rdf.end(); ++v) { - _model->add_statement(base_rdf_node, - AtomRDF::atom_to_node(*_model, v->first), - AtomRDF::atom_to_node(*_model, v->second)); + me->_model->add_statement(base_rdf_node, + AtomRDF::atom_to_node(*me->_model, v->first), + AtomRDF::atom_to_node(*me->_model, v->second)); } return finish(); @@ -205,7 +260,7 @@ Serialiser::to_string(SharedPtr object, * This must be called before any serializing methods. */ void -Serialiser::start_to_filename(const string& filename) +Serialiser::Impl::start_to_filename(const string& filename) { setlocale(LC_NUMERIC, "C"); @@ -235,19 +290,20 @@ Serialiser::start_to_string(const Raul::Path& root, const string& base_uri) { setlocale(LC_NUMERIC, "C"); - _root_path = root; - _base_uri = base_uri; - _model = new Sord::Model(*_world.rdf_world(), base_uri); - _mode = TO_STRING; + me->_root_path = root; + me->_base_uri = base_uri; + me->_model = new Sord::Model(*me->_world.rdf_world(), base_uri); + me->_mode = Impl::TO_STRING; } -/** Finish a serialization. - * - * If this was a serialization to a string, the serialization output - * will be returned, otherwise the empty string is returned. - */ -string +std::string Serialiser::finish() +{ + return me->finish(); +} + +std::string +Serialiser::Impl::finish() { string ret = ""; if (_mode == TO_FILE) { @@ -264,7 +320,7 @@ Serialiser::finish() } Sord::Node -Serialiser::path_rdf_node(const Path& path) +Serialiser::Impl::path_rdf_node(const Path& path) { assert(_model); assert(path == _root_path || path.is_child_of(_root_path)); @@ -275,26 +331,26 @@ Serialiser::path_rdf_node(const Path& path) void Serialiser::serialise(SharedPtr object) throw (std::logic_error) { - if (!_model) + if (!me->_model) throw std::logic_error("serialise called without serialization in progress"); SharedPtr patch = PtrCast(object); if (patch) { - const Sord::URI patch_id(_model->world(), ""); - serialise_patch(patch, patch_id); + const Sord::URI patch_id(me->_model->world(), ""); + me->serialise_patch(patch, patch_id); return; } SharedPtr node = PtrCast(object); if (node) { - const Sord::URI plugin_id(_model->world(), node->plugin()->uri().str()); - serialise_node(node, plugin_id, path_rdf_node(node->path())); + const Sord::URI plugin_id(me->_model->world(), node->plugin()->uri().str()); + me->serialise_node(node, plugin_id, me->path_rdf_node(node->path())); return; } SharedPtr port = PtrCast(object); if (port) { - serialise_port(port.get(), Resource::DEFAULT, path_rdf_node(port->path())); + me->serialise_port(port.get(), Resource::DEFAULT, me->path_rdf_node(port->path())); return; } @@ -303,7 +359,8 @@ Serialiser::serialise(SharedPtr object) throw (std::logic_err } void -Serialiser::serialise_patch(SharedPtr patch, const Sord::Node& patch_id) +Serialiser::Impl::serialise_patch(SharedPtr patch, + const Sord::Node& patch_id) { assert(_model); Sord::World& world = _model->world(); @@ -413,9 +470,9 @@ Serialiser::serialise_patch(SharedPtr patch, const Sord::Node& patc } void -Serialiser::serialise_node(SharedPtr node, - const Sord::Node& class_id, - const Sord::Node& node_id) +Serialiser::Impl::serialise_node(SharedPtr node, + const Sord::Node& class_id, + const Sord::Node& node_id) { _model->add_statement(node_id, Sord::Curie(_model->world(), "rdf:type"), @@ -440,9 +497,9 @@ Serialiser::serialise_node(SharedPtr node, } void -Serialiser::serialise_port(const Port* port, - Resource::Graph context, - const Sord::Node& port_id) +Serialiser::Impl::serialise_port(const Port* port, + Resource::Graph context, + const Sord::Node& port_id) { Sord::World& world = _model->world(); @@ -491,15 +548,25 @@ Serialiser::serialise_port(const Port* port, } void -Serialiser::serialise_connection(const Sord::Node& parent, - SharedPtr connection) throw (std::logic_error) +Serialiser::serialise_connection(const Sord::Node& parent, + SharedPtr connection) + throw (std::logic_error) { - Sord::World& world = _model->world(); + return me->serialise_connection(parent, connection); +} +void +Serialiser::Impl::serialise_connection(const Sord::Node& parent, + SharedPtr connection) + throw (std::logic_error) +{ if (!_model) throw std::logic_error( "serialise_connection called without serialization in progress"); + + Sord::World& world = _model->world(); + const Sord::Node src = path_rdf_node(connection->src_port_path()); const Sord::Node dst = path_rdf_node(connection->dst_port_path()); const Sord::Node connection_id = Sord::Node::blank_id(*_world.rdf_world()); @@ -522,9 +589,9 @@ skip_property(const Sord::Node& predicate) } void -Serialiser::serialise_properties(const GraphObject* o, - Ingen::Resource::Graph context, - Sord::Node id) +Serialiser::Impl::serialise_properties(const GraphObject* o, + Ingen::Resource::Graph context, + Sord::Node id) { const GraphObject::Properties props = o->properties(context); diff --git a/src/serialisation/Serialiser.hpp b/src/serialisation/Serialiser.hpp deleted file mode 100644 index fdc7b423..00000000 --- a/src/serialisation/Serialiser.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard - * - * Ingen 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. - * - * Ingen 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 INGEN_SERIALISATION_SERIALISER_HPP -#define INGEN_SERIALISATION_SERIALISER_HPP - -#include -#include -#include -#include -#include - -#include "raul/Path.hpp" -#include "raul/SharedPtr.hpp" - -#include "sord/sordmm.hpp" - -#include "ingen/GraphObject.hpp" -#include "shared/Store.hpp" - -namespace Ingen { - -class Plugin; -class GraphObject; -class Patch; -class Node; -class Port; -class Connection; - -namespace Shared { class World; } - -namespace Serialisation { - -/** Serialises Ingen objects (patches, nodes, etc) to RDF. - * - * \ingroup IngenClient - */ -class Serialiser -{ -public: - Serialiser(Shared::World& world, SharedPtr store); - - typedef GraphObject::Properties Properties; - - void to_file(SharedPtr object, - const std::string& filename); - - void write_bundle(SharedPtr patch, - const std::string& uri); - - std::string to_string(SharedPtr object, - const std::string& base_uri, - const Properties& extra_rdf); - - void start_to_string(const Raul::Path& root, - const std::string& base_uri); - - void serialise(SharedPtr object) throw (std::logic_error); - - void serialise_connection(const Sord::Node& parent, - SharedPtr c) throw (std::logic_error); - - std::string finish(); - -private: - enum Mode { TO_FILE, TO_STRING }; - - void start_to_filename(const std::string& filename); - - void serialise_patch(SharedPtr p, - const Sord::Node& id); - - void serialise_node(SharedPtr n, - const Sord::Node& class_id, - const Sord::Node& id); - - void serialise_port(const Port* p, - Resource::Graph context, - const Sord::Node& id); - - void serialise_properties(const GraphObject* o, - Resource::Graph context, - Sord::Node id); - - Sord::Node path_rdf_node(const Raul::Path& path); - - void write_manifest(const std::string& bundle_path, - SharedPtr patch, - const std::string& patch_symbol); - - Raul::Path _root_path; - SharedPtr _store; - Mode _mode; - std::string _base_uri; - Shared::World& _world; - Sord::Model* _model; -}; - -} // namespace Serialisation -} // namespace Ingen - -#endif // INGEN_SERIALISATION_SERIALISER_HPP diff --git a/src/serialisation/names.hpp b/src/serialisation/names.hpp deleted file mode 100644 index a65058c4..00000000 --- a/src/serialisation/names.hpp +++ /dev/null @@ -1,24 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2010-2011 David Robillard - * - * Ingen 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. - * - * Ingen 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 INGEN_SERIALISATION_NAMES_HPP -#define INGEN_SERIALISATION_NAMES_HPP - -#define INGEN_PATCH_FILE_EXT ".ttl" -#define INGEN_BUNDLE_EXT ".ingen" - -#endif // INGEN_SERIALISATION_NAMES_HPP diff --git a/src/serialisation/serialisation.cpp b/src/serialisation/serialisation.cpp index 48911b66..af6a9a6d 100644 --- a/src/serialisation/serialisation.cpp +++ b/src/serialisation/serialisation.cpp @@ -18,8 +18,8 @@ #include "shared/Module.hpp" #include "shared/World.hpp" -#include "Parser.hpp" -#include "Serialiser.hpp" +#include "ingen/serialisation/Parser.hpp" +#include "ingen/serialisation/Serialiser.hpp" using namespace Ingen; diff --git a/src/server/HTTPClientSender.cpp b/src/server/HTTPClientSender.cpp index 06534eb3..a71701eb 100644 --- a/src/server/HTTPClientSender.cpp +++ b/src/server/HTTPClientSender.cpp @@ -20,7 +20,7 @@ #include "raul/log.hpp" #include "raul/Atom.hpp" #include "raul/AtomRDF.hpp" -#include "serialisation/Serialiser.hpp" +#include "ingen/serialisation/Serialiser.hpp" #include "shared/World.hpp" #include "HTTPClientSender.hpp" #include "Engine.hpp" diff --git a/src/server/HTTPEngineReceiver.cpp b/src/server/HTTPEngineReceiver.cpp index 4284c51a..ef0e1ee3 100644 --- a/src/server/HTTPEngineReceiver.cpp +++ b/src/server/HTTPEngineReceiver.cpp @@ -28,8 +28,8 @@ #include "ingen/ClientInterface.hpp" #include "shared/Module.hpp" -#include "serialisation/Parser.hpp" -#include "serialisation/Serialiser.hpp" +#include "ingen/serialisation/Parser.hpp" +#include "ingen/serialisation/Serialiser.hpp" #include "ClientBroadcaster.hpp" #include "Engine.hpp" diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index e78c33af..cc258fb3 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -24,7 +24,7 @@ #ifdef INGEN_JACK_SESSION #include #include -#include "serialisation/Serialiser.hpp" +#include "ingen/serialisation/Serialiser.hpp" #endif #include "raul/log.hpp" diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 4419a884..700c2a72 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -41,7 +41,7 @@ #include "server/ThreadManager.hpp" #include "ingen/ServerInterface.hpp" #include "shared/World.hpp" -#include "serialisation/Parser.hpp" +#include "ingen/serialisation/Parser.hpp" #include "shared/Configuration.hpp" #include "shared/runtime_paths.hpp" -- cgit v1.2.1