abstract_value.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* abstract_value.h - Node abstract Value
  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. #ifndef CORE_NODE_ABSTRACT_VALUE_H_D0A0875B_B140_5BFA_9B2E_C7C291245E53
  18. #define CORE_NODE_ABSTRACT_VALUE_H_D0A0875B_B140_5BFA_9B2E_C7C291245E53
  19. #include <boost/uuid/uuid.hpp>
  20. #include <boost/uuid/uuid_generators.hpp>
  21. #include <core/std/any.h>
  22. #include <core/log/simple_exception_log.h>
  23. #include <core/log/global.h>
  24. #include "notify.h"
  25. #include "has_id.h"
  26. #include "abstract_list.h"
  27. #include "cast.h"
  28. namespace rainynite::core {
  29. using NodeId = boost::uuids::uuid;
  30. using NodeIdGenerator = boost::uuids::random_generator;
  31. class Enabled {
  32. public:
  33. explicit Enabled(bool value=true) :
  34. is_enabled(value)
  35. {}
  36. void set_enabled(bool value) {
  37. is_enabled = value;
  38. }
  39. bool enabled() const {
  40. return is_enabled;
  41. }
  42. private:
  43. bool is_enabled;
  44. };
  45. class AbstractValue :
  46. public AbstractNotify,
  47. public HasId<NodeId, NodeIdGenerator>,
  48. public Enabled
  49. {
  50. public:
  51. virtual bool is_const() const {
  52. return false;
  53. }
  54. virtual Type get_type() const = 0;
  55. virtual any get_any(shared_ptr<Context> context) const noexcept = 0;
  56. virtual void set_any(any const& /*value*/) {
  57. throw NodeAccessError("Cannot set");
  58. }
  59. virtual bool can_set_any(any const& /*value*/) const {
  60. return false;
  61. }
  62. virtual any static_any() const {
  63. throw NodeAccessError("No static value");
  64. }
  65. virtual void set_source(shared_ptr<AbstractValue> /*source*/) {
  66. throw NodeAccessError("Cannot set source node");
  67. }
  68. virtual bool can_set_source(shared_ptr<AbstractValue> /*source*/) const {
  69. return false;
  70. }
  71. /**
  72. * Get list of NodeInContext links if this node is a list.
  73. *
  74. * This method exists to allow nodes performing operations on lists without
  75. * necessarily calculating each list element value. It returns list of
  76. * NodeInContext in order to support dynamic list nodes that change context
  77. * for their children.
  78. */
  79. vector<NodeInContext> list_links(shared_ptr<Context> ctx) const noexcept {
  80. if (!enabled())
  81. return {};
  82. try {
  83. return get_list_links(ctx);
  84. } catch (...) {
  85. // TODO: report
  86. return {};
  87. }
  88. }
  89. protected:
  90. /// list_links virtual implementation.
  91. virtual vector<NodeInContext> get_list_links(shared_ptr<Context> /*ctx*/) const {
  92. throw NodeAccessError("This node is not a list");
  93. }
  94. };
  95. template <typename T>
  96. constexpr bool is_vector = false;
  97. template <typename U>
  98. constexpr bool is_vector<vector<U>> = true;
  99. template <typename T>
  100. class BaseValue :
  101. public AbstractValue,
  102. public HasExceptionLogger
  103. {
  104. public:
  105. BaseValue() :
  106. HasExceptionLogger(make_shared<GlobalLog<SimpleExceptionLogger>>())
  107. {}
  108. public:
  109. /**
  110. * Get value of this node in given context
  111. *
  112. * Any exceptions that are thrown during node calculation should be
  113. * recorded in log (TODO; not yet implemented).
  114. */
  115. T value(shared_ptr<Context> context) const noexcept {
  116. if (!enabled())
  117. return default_value(context);
  118. try {
  119. return get(context);
  120. } catch (std::exception const& ex) {
  121. log_exception_from_this(ex);
  122. return {};
  123. } catch (...) {
  124. log_exception_from_this(NodeAccessError("Unknown error in BaseValue::value()"));
  125. return {};
  126. }
  127. }
  128. public:
  129. /**
  130. * Get value of this node in given context - may throw
  131. *
  132. * TODO: make protected
  133. */
  134. virtual T get(shared_ptr<Context> context) const {
  135. if constexpr (is_vector<T>) {
  136. using E = typename T::value_type;
  137. T result;
  138. auto links = list_links(context);
  139. bool error = false;
  140. std::transform(
  141. links.begin(),
  142. links.end(),
  143. std::back_inserter(result),
  144. [&error](NodeInContext e) {
  145. if (auto node = base_value_cast<E>(std::move(e.node)))
  146. return node->value(e.context);
  147. error = true;
  148. return E{};
  149. }
  150. );
  151. if (error)
  152. throw NodeAccessError("Got wrong element type");
  153. return result;
  154. } else {
  155. (void) context;
  156. throw NodeAccessError("Get not implemented in node");
  157. }
  158. }
  159. /// Value to return when node is disabled
  160. virtual T default_value(shared_ptr<Context> /*ctx*/) const noexcept {
  161. return {};
  162. }
  163. virtual void set(T /*value*/) {
  164. throw NodeAccessError("Cannot set");
  165. }
  166. virtual T& mod() {
  167. throw NodeAccessError("Cannot set");
  168. }
  169. virtual bool can_set() const {
  170. return false;
  171. }
  172. public:
  173. Type get_type() const override {
  174. return typeid(T);
  175. }
  176. any get_any(shared_ptr<Context> context) const noexcept override {
  177. return value(context);
  178. }
  179. void set_any(any const& value_) override {
  180. set(any_cast<T>(value_));
  181. }
  182. bool can_set_any(any const& value_) const override {
  183. return can_set() && value_.type() == typeid(T);
  184. }
  185. public:
  186. static Type static_type() {
  187. return typeid(T);
  188. }
  189. };
  190. } // namespace rainynite::core
  191. #endif