summaryrefslogtreecommitdiffstats
path: root/src/Resource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Resource.cpp')
-rw-r--r--src/Resource.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/Resource.cpp b/src/Resource.cpp
new file mode 100644
index 00000000..13959a13
--- /dev/null
+++ b/src/Resource.cpp
@@ -0,0 +1,218 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2012 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or 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 Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <utility>
+
+#include "ingen/Resource.hpp"
+#include "ingen/shared/URIs.hpp"
+#include "raul/Atom.hpp"
+#include "raul/log.hpp"
+
+using namespace std;
+
+namespace Ingen {
+
+void
+Resource::add_property(const Raul::URI& uri,
+ const Raul::Atom& value,
+ Graph ctx)
+{
+ // Ignore duplicate statements
+ typedef Resource::Properties::const_iterator iterator;
+ const std::pair<iterator, iterator> range = _properties.equal_range(uri);
+ for (iterator i = range.first; i != range.second && i != _properties.end(); ++i) {
+ if (i->second == value && i->second.context() == ctx) {
+ return;
+ }
+ }
+
+ const Raul::Atom& v = _properties.insert(make_pair(uri, Property(value, ctx)))->second;
+ on_property(uri, v);
+}
+
+const Raul::Atom&
+Resource::set_property(const Raul::URI& uri,
+ const Raul::Atom& value,
+ Resource::Graph ctx)
+{
+ // Erase existing property in this context
+ for (Properties::iterator i = _properties.find(uri);
+ (i != _properties.end()) && (i->first == uri);) {
+ Properties::iterator next = i;
+ ++next;
+ if (i->second.context() == ctx) {
+ _properties.erase(i);
+ }
+ i = next;
+ }
+
+ // Insert new property
+ const Raul::Atom& v = _properties.insert(make_pair(uri, Property(value, ctx)))->second;
+ on_property(uri, v);
+ return v;
+}
+
+void
+Resource::remove_property(const Raul::URI& uri, const Raul::Atom& value)
+{
+ if (value == _uris.wildcard) {
+ _properties.erase(uri);
+ } else {
+ Properties::iterator i = _properties.find(uri);
+ for (; (i != _properties.end()) && (i->first == uri); ++i) {
+ if (i->second == value) {
+ _properties.erase(i);
+ return;
+ }
+ }
+ }
+}
+
+bool
+Resource::has_property(const Raul::URI& uri, const Raul::Atom& value) const
+{
+ Properties::const_iterator i = _properties.find(uri);
+ for (; (i != _properties.end()) && (i->first == uri); ++i) {
+ if (i->second == value) {
+ return true;
+ }
+ }
+ return false;
+}
+
+const Raul::Atom&
+Resource::set_property(const Raul::URI& uri, const Raul::Atom& value) const
+{
+ return const_cast<Resource*>(this)->set_property(uri, value);
+}
+
+const Raul::Atom&
+Resource::get_property(const Raul::URI& uri) const
+{
+ static const Raul::Atom nil;
+ Properties::const_iterator i = _properties.find(uri);
+ return (i != _properties.end()) ? i->second : nil;
+}
+
+bool
+Resource::type(const Shared::URIs& uris,
+ const Properties& properties,
+ bool& patch,
+ bool& node,
+ bool& port,
+ bool& is_output)
+{
+ typedef Resource::Properties::const_iterator iterator;
+ const std::pair<iterator, iterator> types_range = properties.equal_range(uris.rdf_type);
+
+ patch = node = port = is_output = false;
+ for (iterator i = types_range.first; i != types_range.second; ++i) {
+ const Raul::Atom& atom = i->second;
+ if (atom.type() != uris.forge.URI && atom.type() != uris.forge.URID) {
+ Raul::warn << "[Resource] Non-URI type " << uris.forge.str(atom) << endl;
+ continue;
+ }
+
+ if (atom == uris.ingen_Patch) {
+ patch = true;
+ } else if (atom == uris.ingen_Node) {
+ node = true;
+ } else if (atom == uris.lv2_InputPort) {
+ port = true;
+ is_output = false;
+ } else if (atom == uris.lv2_OutputPort) {
+ port = true;
+ is_output = true;
+ }
+ }
+
+ if (patch && node && !port) { // => patch
+ node = false;
+ return true;
+ } else if (port && (patch || node)) { // nonsense
+ port = false;
+ return false;
+ } else if (patch || node || port) { // recognized type
+ return true;
+ } else { // unknown
+ return false;
+ }
+}
+
+void
+Resource::set_properties(const Properties& p)
+{
+ /* Note a simple loop that calls set_property is inappropriate here since
+ it will not correctly set multiple properties in p (notably rdf:type)
+ */
+
+ // Erase existing properties with matching keys
+ for (Properties::const_iterator i = p.begin(); i != p.end(); ++i) {
+ _properties.erase(i->first);
+ }
+
+ // Set new properties
+ add_properties(p);
+}
+
+void
+Resource::add_properties(const Properties& p)
+{
+ typedef Resource::Properties::const_iterator iterator;
+ for (iterator i = p.begin(); i != p.end(); ++i)
+ add_property(i->first, i->second, i->second.context());
+}
+
+void
+Resource::remove_properties(const Properties& p)
+{
+ typedef Resource::Properties::const_iterator iterator;
+ for (iterator i = p.begin(); i != p.end(); ++i) {
+ if (i->second == _uris.wildcard) {
+ _properties.erase(i->first);
+ } else {
+ for (Properties::iterator j = _properties.find(i->first);
+ (j != _properties.end()) && (j->first == i->first); ++j) {
+ if (j->second == i->second) {
+ _properties.erase(j);
+ break;
+ }
+ }
+ }
+ }
+}
+
+Resource::Properties
+Resource::properties(Resource::Graph ctx) const
+{
+ if (ctx == Resource::DEFAULT) {
+ return properties();
+ }
+
+ typedef Resource::Properties::const_iterator iterator;
+
+ Properties props;
+ for (iterator i = _properties.begin(); i != _properties.end(); ++i) {
+ if (i->second.context() == Resource::DEFAULT
+ || i->second.context() == ctx) {
+ props.insert(make_pair(i->first, i->second));
+ }
+ }
+
+ return props;
+}
+
+} // namespace Ingen