diff options
Diffstat (limited to 'src/serialisation')
-rw-r--r-- | src/serialisation/Parser.cpp | 652 | ||||
-rw-r--r-- | src/serialisation/Parser.hpp | 128 | ||||
-rw-r--r-- | src/serialisation/Serialiser.cpp | 167 | ||||
-rw-r--r-- | src/serialisation/Serialiser.hpp | 116 | ||||
-rw-r--r-- | src/serialisation/names.hpp | 24 | ||||
-rw-r--r-- | src/serialisation/serialisation.cpp | 4 |
6 files changed, 469 insertions, 622 deletions
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<PatchRecord> 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<Raul::Path> parent, - boost::optional<Raul::Symbol> symbol, - boost::optional<GraphObject::Properties> 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<Path> 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<Raul::Path> parent, - boost::optional<Raul::Symbol> symbol, - boost::optional<GraphObject::Properties> 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<Raul::Path> 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<Path> -Parser::parse(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - Glib::ustring document_uri, - boost::optional<Raul::Path> data_path, - boost::optional<Raul::Path> parent, - boost::optional<Raul::Symbol> symbol, - boost::optional<GraphObject::Properties> 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<Sord::Node> > 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<Sord::Node> types; - types.insert(rdf_class); - subjects.insert(make_pair(subject, types)); - } else { - s->second.insert(rdf_class); - } - } - - // Parse and create each subject - boost::optional<Path> ret; - boost::optional<Path> root_path; - for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) { - const Sord::Node& subject = i->first; - const std::set<Sord::Node>& 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<Sord::Node>::const_iterator t = types.begin(); - t != types.end(); ++t) { - LOG(error) << " :: " << *t << endl; - assert((*t).is_uri()); - } - return boost::optional<Path>(); - } - - 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<Path> -Parser::parse_patch(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject_node, - boost::optional<Raul::Path> parent, - boost::optional<Raul::Symbol> a_symbol, - boost::optional<GraphObject::Properties> data) +static boost::optional<Raul::Path> +parse( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + Glib::ustring document_uri, + boost::optional<Raul::Path> data_path = boost::optional<Raul::Path>(), + boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(), + boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), + boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>()); + +static boost::optional<Raul::Path> +parse_patch( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(), + boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), + boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>()); + + +static boost::optional<Raul::Path> +parse_node( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& path, + boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>()); + + +static bool +parse_properties( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::URI& uri, + boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>()); + +static bool +parse_connections( + Shared::World* world, + CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& patch); + +static boost::optional<Path> +parse_node(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& path, + boost::optional<GraphObject::Properties> 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<Path>(); + } + + 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<Path> +parse_patch(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + const Sord::Node& subject_node, + boost::optional<Raul::Path> parent, + boost::optional<Raul::Symbol> a_symbol, + boost::optional<GraphObject::Properties> data) { const Sord::URI ingen_node(*world->rdf_world(), NS_INGEN "node"); const Sord::URI ingen_polyphony(*world->rdf_world(), NS_INGEN "polyphony"); @@ -494,71 +381,12 @@ Parser::parse_patch(Ingen::Shared::World* world, return patch_path; } -boost::optional<Path> -Parser::parse_node(Ingen::Shared::World* world, - Ingen::CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& path, - boost::optional<GraphObject::Properties> 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<Path>(); - } - - 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; -} - -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<GraphObject::Properties> 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<GraphObject::Properties> 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<Path> +parse(Ingen::Shared::World* world, + Ingen::CommonInterface* target, + Sord::Model& model, + Glib::ustring document_uri, + boost::optional<Raul::Path> data_path, + boost::optional<Raul::Path> parent, + boost::optional<Raul::Symbol> symbol, + boost::optional<GraphObject::Properties> 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<Sord::Node> > 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<Sord::Node> types; + types.insert(rdf_class); + subjects.insert(make_pair(subject, types)); + } else { + s->second.insert(rdf_class); + } + } + + // Parse and create each subject + boost::optional<Path> ret; + boost::optional<Path> root_path; + for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) { + const Sord::Node& subject = i->first; + const std::set<Sord::Node>& 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<Sord::Node>::const_iterator t = types.begin(); + t != types.end(); ++t) { + LOG(error) << " :: " << *t << endl; + assert((*t).is_uri()); + } + return boost::optional<Path>(); + } + + 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<PatchRecord> 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<Raul::Path> parent, + boost::optional<Raul::Symbol> symbol, + boost::optional<GraphObject::Properties> 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<Path> 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<Raul::Path> parent, + boost::optional<Raul::Symbol> symbol, + boost::optional<GraphObject::Properties> 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<Raul::Path> 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 <http://drobilla.net> - * - * 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 <string> -#include <list> - -#include <boost/optional.hpp> -#include <glibmm/ustring.h> - -#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<Raul::Path> parent = boost::optional<Raul::Path>(), - boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), - boost::optional<Properties> data = boost::optional<Properties>()); - - virtual bool parse_string( - Shared::World* world, - CommonInterface* target, - const Glib::ustring& str, - const Glib::ustring& base_uri, - boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(), - boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), - boost::optional<Properties> data = boost::optional<Properties>()); - - 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<PatchRecord> PatchRecords; - - virtual PatchRecords find_patches(Shared::World* world, - SerdEnv* env, - const Glib::ustring& manifest_uri); - -private: - boost::optional<Raul::Path> parse( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - Glib::ustring document_uri, - boost::optional<Raul::Path> data_path = boost::optional<Raul::Path>(), - boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(), - boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), - boost::optional<Properties> data = boost::optional<Properties>()); - - boost::optional<Raul::Path> parse_patch( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(), - boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), - boost::optional<Properties> data = boost::optional<Properties>()); - - boost::optional<Raul::Path> parse_node( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& path, - boost::optional<Properties> data = boost::optional<Properties>()); - - bool parse_properties( - Shared::World* world, - CommonInterface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::URI& uri, - boost::optional<Properties> data = boost::optional<Properties>()); - - 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 <cstdlib> #include <cstring> #include <fstream> +#include <map> #include <stdexcept> #include <string> #include <utility> @@ -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<Shared::Store> 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<const Patch> p, + const Sord::Node& id); + + void serialise_node(SharedPtr<const Node> 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<const Patch> patch, + const std::string& uri); + + Sord::Node path_rdf_node(const Raul::Path& path); + + void write_manifest(const std::string& bundle_path, + SharedPtr<const Patch> patch, + const std::string& patch_symbol); + + void serialise_connection(const Sord::Node& parent, + SharedPtr<const Connection> c) + throw (std::logic_error); + + std::string finish(); + + Raul::Path _root_path; + SharedPtr<Shared::Store> _store; + Mode _mode; + std::string _base_uri; + Shared::World& _world; + Sord::Model* _model; +}; + + Serialiser::Serialiser(Shared::World& world, SharedPtr<Shared::Store> store) - : _root_path("/") - , _store(store) - , _world(world) -{ -} + : me(new Impl(world, store)) +{} void Serialiser::to_file(SharedPtr<const GraphObject> 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<const Patch> patch, - const std::string& patch_symbol) +Serialiser::Impl::write_manifest(const std::string& bundle_path, + SharedPtr<const Patch> 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, @@ -150,6 +198,13 @@ void Serialiser::write_bundle(SharedPtr<const Patch> patch, const std::string& uri) { + me->write_bundle(patch, uri); +} + +void +Serialiser::Impl::write_bundle(SharedPtr<const Patch> patch, + const std::string& uri) +{ Glib::ustring path = ""; try { path = Glib::filename_from_uri(uri); @@ -169,7 +224,7 @@ Serialiser::write_bundle(SharedPtr<const Patch> 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<const GraphObject> 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<const GraphObject> 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,20 +290,21 @@ 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) { _model->write_to_file(_base_uri, SERD_TURTLE); @@ -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<const GraphObject> object) throw (std::logic_error) { - if (!_model) + if (!me->_model) throw std::logic_error("serialise called without serialization in progress"); SharedPtr<const Patch> patch = PtrCast<const Patch>(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<const Node> node = PtrCast<const Node>(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<const Port> port = PtrCast<const Port>(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<const GraphObject> object) throw (std::logic_err } void -Serialiser::serialise_patch(SharedPtr<const Patch> patch, const Sord::Node& patch_id) +Serialiser::Impl::serialise_patch(SharedPtr<const Patch> patch, + const Sord::Node& patch_id) { assert(_model); Sord::World& world = _model->world(); @@ -413,9 +470,9 @@ Serialiser::serialise_patch(SharedPtr<const Patch> patch, const Sord::Node& patc } void -Serialiser::serialise_node(SharedPtr<const Node> node, - const Sord::Node& class_id, - const Sord::Node& node_id) +Serialiser::Impl::serialise_node(SharedPtr<const Node> 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<const Node> 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<const Connection> connection) throw (std::logic_error) +Serialiser::serialise_connection(const Sord::Node& parent, + SharedPtr<const Connection> 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<const Connection> 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 <http://drobilla.net> - * - * 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 <cassert> -#include <map> -#include <stdexcept> -#include <string> -#include <utility> - -#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<Shared::Store> store); - - typedef GraphObject::Properties Properties; - - void to_file(SharedPtr<const GraphObject> object, - const std::string& filename); - - void write_bundle(SharedPtr<const Patch> patch, - const std::string& uri); - - std::string to_string(SharedPtr<const GraphObject> 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<const GraphObject> object) throw (std::logic_error); - - void serialise_connection(const Sord::Node& parent, - SharedPtr<const Connection> 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<const Patch> p, - const Sord::Node& id); - - void serialise_node(SharedPtr<const Node> 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<const Patch> patch, - const std::string& patch_symbol); - - Raul::Path _root_path; - SharedPtr<Shared::Store> _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 <http://drobilla.net> - * - * 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; |