Rose
StructuredTypes.h
Go to the documentation of this file.
1 
9 #pragma once
10 
11 #include <algorithm>
12 #include <exception>
13 #include <memory>
14 #include <vector>
15 #include <iostream>
16 #include <sstream>
17 #include "Utilities.h"
18 
19 namespace rose {
20 
21  class NodeTypeError : std::runtime_error {
22  public:
23  explicit NodeTypeError(const char *what) : std::runtime_error(what) {}
24  explicit NodeTypeError(const std::string &what) : std::runtime_error(what) {}
25  NodeTypeError(const NodeTypeError &other) noexcept = default;
26  };
27 
28  class NodeRangeError : std::out_of_range {
29  public:
30  explicit NodeRangeError(const char *what) : std::out_of_range(what) {}
31 
32  explicit NodeRangeError(const std::string &what) : std::out_of_range(what) {}
33 
34  NodeRangeError(const NodeRangeError &other) noexcept = default;
35  };
36 
41  class ContainerTypeError : public std::runtime_error {
42  public:
43  ContainerTypeError() = delete;
44  explicit ContainerTypeError(const std::string &what) : std::runtime_error(what) {}
45  explicit ContainerTypeError(const char *what) : std::runtime_error(what) {}
46  ContainerTypeError(const ContainerTypeError& other) = default;
47  };
48 
49  class Container;
50 
51  using IdPathElement = std::pair<std::string,std::string>;
52 
54  struct IdPath : public std::vector<IdPathElement> {
55  bool absolutePath{};
56  static constexpr char PathSep = '/';
57  static constexpr char ElementSep = ':';
58  static constexpr std::string_view PathWild = "*";
59  static constexpr std::string_view PathWildOne = "?";
60  static constexpr std::string_view PathParent = "..";
61 
62  explicit IdPath(bool absolute = false) : std::vector<IdPathElement>(), absolutePath(absolute) {}
63 
64  explicit IdPath(const IdPathElement& element, bool absolute = false) : IdPath(absolute) {
65  emplace_back(element);
66  }
67 
68  [[nodiscard]] std::string str() const {
69  bool notFirst = false;
70  std::stringstream strm{};
71  for (auto &element : *this) {
72  if (absolutePath || notFirst) {
73  strm << PathSep;
74  }
75  strm << element.first;
76  if (!element.second.empty())
77  strm << ElementSep << element.second;
78  notFirst = true;
79  }
80  return strm.str();
81  }
82 
83  std::tuple<bool, int> compare(const IdPath& target) {
84  bool wildCard = false;
85  int score = 0;
86  auto tgt = target.rbegin();
87  for (auto& srch : ReverseContainerView(*this)) {
88  if (tgt == target.rend())
89  return std::make_tuple(false, 0);
90  *tgt;
91 
92  if (wildCard) {
93  if (srch.first == PathWild || srch.first == PathWildOne)
94  continue;
95  while ((srch.first != (*tgt).second) && (srch.first != (*tgt).first)) {
96  if (++tgt == target.rend())
97  return std::make_tuple(false, 0);
98  }
99  if (srch.first == (*tgt).second)
100  ++score;
101  wildCard = false;
102  } else {
103  if (srch.first == (*tgt).second) {
104  ++score;
105  } else if (srch.first != (*tgt).first) {
106  if (srch.first != PathWildOne) {
107  if (srch.first == PathWild) {
108  wildCard = true;
109  } else {
110  return std::make_tuple(false, 0);
111  }
112  }
113  }
114  }
115  ++tgt;
116  }
117  return std::make_tuple(true, score);
118  }
119  };
120 
121  template<typename I>
122  inline IdPath parsePathIdString(I inputString) {
123  std::stringstream strm;
124  if constexpr (std::is_same_v<std::string_view,I>) {
125  strm.str(std::string{inputString});
126  } else {
127  strm.str(inputString);
128  }
129  IdPath idPath{};
130  std::string tmp;
131  while (std::getline(strm, tmp, IdPath::PathSep)) {
132  if (idPath.empty() && tmp.empty())
133  idPath.absolutePath = true;
134  else if (!tmp.empty()) {
135  std::string e1{}, e2{};
136  std::stringstream tstrm{tmp};
137  std::getline(tstrm, e1, IdPath::ElementSep);
138  std::getline(tstrm, e2, IdPath::ElementSep);
139  idPath.emplace_back(e1,e2);
140  }
141  }
142  return idPath;
143  }
144 
148  struct Id {
149  std::string_view idString;
150 
151  constexpr explicit operator bool() const noexcept {
152  return !idString.empty();
153  }
154  };
155 
160  class Node : public std::enable_shared_from_this<Node> {
161  public:
162  friend class Container;
163  using NodePtr = std::shared_ptr<Node>;
164 
165  protected:
167  std::weak_ptr<Container> mContainer{};
168 
170  Id mId{};
171 
172  public:
173  Node() = default;
174 
179  explicit Node(const std::shared_ptr<Container> &container);
180 
181  virtual ~Node() = default;
182 
183  static constexpr std::string_view id = "Node";
184  virtual std::string_view nodeId() const noexcept {
185  return id;
186  }
187 
189  void setId(const Id& nodeId) noexcept {
190  mId = nodeId;
191  }
192 
194  std::string_view getId() const {
195  return mId.idString;
196  }
197 
199  IdPath getIdPath() const;
200 
206  virtual void addedToContainer() {
207  }
208 
209  std::shared_ptr<Container> container() {
210  if (mContainer.expired())
211  return nullptr;
212  return mContainer.lock();
213  }
214 
215  std::shared_ptr<Container> container() const {
216  if (mContainer.expired())
217  return nullptr;
218  return mContainer.lock();
219  }
220 
221  template<typename C>
222  std::shared_ptr<C> containerAs() {
223  auto c = container();
224  if (c) {
225  return std::dynamic_pointer_cast<C>(c);
226  }
227  return nullptr;
228  }
229 
230  template<typename C>
231  std::shared_ptr<C> containerAs() const {
232  auto c = container();
233  if (c) {
234  return std::dynamic_pointer_cast<C>(c);
235  }
236  return nullptr;
237  }
238 
244  template<typename NodeType>
245  static std::shared_ptr<NodeType> create() {
246  return std::make_shared<NodeType>();
247  }
248 
256  template<typename NodeType, typename ... Args>
257  static std::shared_ptr<NodeType> create(Args ... args) {
258  return std::make_shared<NodeType>(args ...);
259  }
260 
270  template<typename NodeType, typename ContainerType, typename ... Args>
271  static std::shared_ptr<NodeType> add(ContainerType container, Args ... args) {
272  static_assert(std::is_base_of_v<std::shared_ptr<Container>, ContainerType>,
273  "ContainerType must be derived from Container.");
274  auto node = std::make_shared<NodeType>(args ...);
275  node->mContainer = container;
276  container->add(node);
277  return node;
278  }
279 
284  std::shared_ptr<const Node> getNode() const {
285  return shared_from_this();
286  }
287 
292  std::shared_ptr<Node> getNode() {
293  return shared_from_this();
294  }
295 
302  template<typename NodeType>
303  std::shared_ptr<const Node> getNode() const {
304  return std::dynamic_pointer_cast<NodeType>(shared_from_this());
305  }
306 
313  template<typename NodeType>
314  std::shared_ptr<NodeType> getNode() {
315  return std::dynamic_pointer_cast<NodeType>(shared_from_this());
316  }
317 
318  std::shared_ptr<Node> remove();
319  };
320 
325  class Container : public Node, public std::vector<Node::NodePtr> {
326  public:
327  ~Container() override = default;
328 
329  static constexpr std::string_view id = "Container";
330  std::string_view nodeId() const noexcept override {
331  return id;
332  }
333 
334  virtual void add(const std::shared_ptr<Node> &node) {
335  if (auto container = getNode<Container>(); container) {
336  container->push_back(node);
337  node->mContainer = container;
338  node->addedToContainer();
339  }
340  }
341 
342  void remove(const std::shared_ptr<Node>& node) {
343  erase(std::remove(begin(), end(), node));
344  }
345  };
346 
347  inline std::shared_ptr<Node> Node::remove() {
348  auto node = shared_from_this();
349  if (auto container = mContainer.lock(); container) {
350  container->remove(node);
351  }
352  return node;
353  }
354 
355  inline IdPath Node::getIdPath() const {
356  auto node = container();
357  auto idPath = node ? node->getIdPath() : IdPath{true};
358  idPath.emplace_back(nodeId(),getId());
359  return idPath;
360  }
361 }
362 
370 template<class NodeClass>
371 inline std::shared_ptr<NodeClass> operator<<(std::shared_ptr<NodeClass> widget, const rose::Id& id) {
372  static_assert(std::is_base_of_v<rose::Node, NodeClass>, "WidgetClass must be derived from rose::Node.");
373  widget->setId(id);
374  return widget;
375 }
376 
377 inline std::ostream& operator<<(std::ostream& ostrm, const rose::IdPath& idPath) {
378  return ostrm << idPath.str();
379 }
std::shared_ptr< NodeClass > operator<<(std::shared_ptr< NodeClass > widget, const rose::Id &id)
An insertion operator to set the Id of a Widget.
Definition: StructuredTypes.h:371
std::shared_ptr< const Node > getNode() const
Get a const std::shared_ptr to this node.
Definition: StructuredTypes.h:284
A container which holds the subordinate Node objects.
Definition: StructuredTypes.h:325
virtual void addedToContainer()
Called when a Node is added to a Container.
Definition: StructuredTypes.h:206
Provide a reverse view of a standard container type.
Definition: Utilities.h:36
std::shared_ptr< Node > getNode()
Get a std::shared_ptr to this node.
Definition: StructuredTypes.h:292
std::shared_ptr< NodeType > getNode()
Get a std::shared_ptr<NodeType> to this node.
Definition: StructuredTypes.h:314
std::string_view getId() const
Get Id.
Definition: StructuredTypes.h:194
IdPath getIdPath() const
Get the Id Path.
Definition: StructuredTypes.h:355
static std::shared_ptr< NodeType > create(Args ... args)
Create a Node with arguments.
Definition: StructuredTypes.h:257
static std::shared_ptr< NodeType > add(ContainerType container, Args ... args)
Create a Node with arguments and add to a Container.
Definition: StructuredTypes.h:271
static std::shared_ptr< NodeType > create()
Create a Node with no arguments.
Definition: StructuredTypes.h:245
std::weak_ptr< Container > mContainer
The Container that holds the Node.
Definition: StructuredTypes.h:167
An exception to indicate an unexpected container type at runtime.
Definition: StructuredTypes.h:41
A class to define a polymorphic member in an N-Array tree.
Definition: StructuredTypes.h:160
A type to specify an Id value.
Definition: StructuredTypes.h:148
Definition: StructuredTypes.h:21
Definition: StructuredTypes.h:28
ToDo: There is an issue that the initial scroll interaction is lost if the click/press lands on a Wid...
Definition: CelestialOverlay.cpp:13
std::shared_ptr< const Node > getNode() const
Get a std::shared_ptr<const NodeType> to this node.
Definition: StructuredTypes.h:303
void setId(const Id &nodeId) noexcept
Set Id.
Definition: StructuredTypes.h:189
A path of objects by Id.
Definition: StructuredTypes.h:54