abstract_node.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* abstract_node.cpp - abstract Node
  2. * Copyright (C) 2017 caryoscelus
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <core/node/abstract_node.h>
  18. #include <core/node/abstract_value.h>
  19. namespace rainynite::core {
  20. BaseOldNode::~BaseOldNode() {
  21. for (auto const& connection : signal_connections) {
  22. connection.disconnect();
  23. }
  24. }
  25. AbstractReference BaseOldNode::get_property(string const& name) const {
  26. auto result = named_storage.find(name);
  27. if (result == named_storage.end())
  28. throw NodeAccessError("Unknown property "+name);
  29. return get_by_id(result->second);
  30. }
  31. void BaseOldNode::set_property(string const& name, AbstractReference ref) {
  32. if (named_storage.count(name) == 0) {
  33. if (name[0] == '_') {
  34. // accept as custom attribute
  35. init_property(name, {}, ref);
  36. } else
  37. throw NodeAccessError("No such property: "+name);
  38. }
  39. set_link(named_storage[name], ref);
  40. }
  41. bool BaseOldNode::remove_property(string const& name) {
  42. if (name[0] != '_')
  43. return false; // can only remove custom props
  44. auto iter = named_storage.find(name);
  45. if (iter == std::end(named_storage))
  46. return false;
  47. auto i = iter->second;
  48. // NOTE: this might be not thread-safe
  49. named_storage.erase(iter);
  50. names_list.erase(names_list.begin()+i);
  51. numbered_storage.erase(numbered_storage.begin()+i);
  52. // reassign links
  53. for (auto& e : named_storage) {
  54. if (e.second > i)
  55. --e.second;
  56. }
  57. return true;
  58. }
  59. size_t BaseOldNode::init_property(string const& name, TypeConstraint type, AbstractReference value) {
  60. size_t id = link_count();
  61. numbered_storage.push_back(value);
  62. names_list.push_back(name);
  63. named_storage[name] = id;
  64. types.push_back(type);
  65. boost::signals2::connection connection;
  66. if (value)
  67. connection = value->subscribe([this]() {
  68. node_changed();
  69. });
  70. signal_connections.push_back(connection);
  71. return id;
  72. }
  73. map<string, AbstractReference> BaseOldNode::get_link_map() const {
  74. map<string, AbstractReference> result;
  75. // TODO: use generic conversion function
  76. for (auto const& e : named_storage) {
  77. result.emplace(e.first, get_by_id(e.second));
  78. }
  79. return result;
  80. }
  81. void BaseOldNode::set_link(size_t i, AbstractReference value) {
  82. if (!get_link_type(i).accept(value->get_type()))
  83. throw NodeAccessError("Node property type mis-match");
  84. signal_connections[i].disconnect();
  85. get_by_id(i) = value;
  86. signal_connections[i] = value->subscribe([this]() {
  87. node_changed();
  88. });
  89. node_changed();
  90. }
  91. } // namespace rainynite::core