CVB++ 15.0
decl_node_map.hpp
1#pragma once
2#pragma once
3
4#include <map>
5#include <memory>
6
7#include "../../global.hpp"
8#include "../../genapi/node_map.hpp"
9#include "../gevserver.hpp"
10
11#include "../_decl/decl_node.hpp"
12#include "../_decl/decl_server.hpp"
13#include "../../genapi/_decl/decl_node_map.hpp"
14
15namespace Cvb
16{
17 CVB_BEGIN_INLINE_NS
18
19 namespace GevServer
20 {
22
24 class NodeMap : public std::enable_shared_from_this<NodeMap>
25 {
26 public:
27 explicit NodeMap(const ServerPtr &server) noexcept;
28
30
34 void *Handle() const noexcept
35 {
36 auto srv = server_.lock();
37 if (!srv)
38 return nullptr;
39
40 return srv->Handle();
41 }
42
44
48 ServerPtr Server()
49 {
50 auto srv = server_.lock();
51 if (!srv)
52 return ServerPtr();
53
54 return srv;
55 }
56
58
62 std::map<String, NodePtr> Nodes() const;
63
71 void AddNode(const String &key, const NodePtr &value)
72 {
73 if (key.empty())
74 throw std::runtime_error("key must not be empty");
75 if (!value)
76 throw std::runtime_error("node must not be null");
77 if (value->NodeMap() != nullptr)
78 if (!nodes_[key].owner_before(value) && !value.owner_before(nodes_[key]))
79 return; // has been added before
80 auto name = value->NameOnly();
81 if (key != name)
82 throw std::runtime_error("key and value->NameOnly() must be equal");
83
84 NativeCall([&]() { return CVB_CALL_CAPI(GSAddNode(Handle(), value->Handle())); });
85
86 // add node map to item
87 value->SetNodeMap(std::const_pointer_cast<NodeMap>(shared_from_this()));
88
89 nodes_[key] = value;
90 }
91
100 void AddNode(const String &key, const NodePtr &value, const NodeList &kind);
101
110 void AddNode(const NodePtr &value)
111 {
112 if (!value)
113 throw std::runtime_error("node must not be null");
114
115 AddNode(value->NameOnly(), value);
116 }
117
126 bool RemoveNode(const Node &node)
127 {
128 return RemoveNode(node.NameOnly());
129 }
130
140 bool RemoveNode(const String &key)
141 {
142 auto node = TryGetNode(key);
143 if (node)
144 {
145 if (node == nullptr)
146 throw std::runtime_error("node to remove must not be null");
147 if (node->NodeMap() != shared_from_this())
148 return false;
149
150 auto it = nodes_.find(node->NameOnly());
151 if (it != nodes_.end())
152 {
153 nodes_.erase(it);
154 NativeCall([&]() { return CVB_CALL_CAPI(GSRemoveNode(Handle(), node->Handle())); });
155 return true;
156 }
157 }
158 return false;
159 }
160
169 bool IsReadOnly() const
170 {
171 auto srv = server_.lock();
172 if (srv)
173 return srv->State() != GevServer::State::Configuration;
174 else
175 throw std::runtime_error("this node map is not attached to a server");
176 }
177
181 String ModelName() const
182 {
183 auto modelName = Node(CVB_LIT("DeviceModelName"));
184 return modelName != nullptr ? modelName->DisplayName() : CVB_LIT("CVGevServer");
185 }
186
193 String ModuleName() const noexcept
194 {
195 return CVB_LIT("Device");
196 }
197
204 String TransportLayerNamespace() const noexcept
205 {
206 return CVB_LIT("GEV");
207 }
208
210
218 String VendorName() const noexcept
219 {
220 auto vendorName = Node(CVB_LIT("DeviceVendorName"));
221 return vendorName != nullptr ? vendorName->DisplayName() : CVB_LIT("STEMMERIMAGING");
222 }
223
225
229 GenApi::NodeMap::GenApiVersion XmlFileSchemaVersion() const noexcept
230 {
231 return GenApi::NodeMap::GenApiVersion(1, 0, 1);
232 }
233
250 GenApi::NodeMap::GenApiVersion XmlFileVersion() const noexcept
251 {
252 return GenApi::NodeMap::GenApiVersion(static_cast<std::uint16_t>(GetInfoAsInt(Info::XMLVersionMajor)),
253 static_cast<std::uint16_t>(GetInfoAsInt(Info::XMLVersionMinor)),
254 static_cast<std::uint16_t>(GetInfoAsInt(Info::XMLVersionSubMinor)));
255 }
256
273 void SetXmlFileVersion(const GenApi::NodeMap::GenApiVersion &genApiVersion) const
274 {
275 SetInfoAsInt(Info::XMLVersionMajor, genApiVersion.Major());
276 SetInfoAsInt(Info::XMLVersionMinor, genApiVersion.Minor());
277 SetInfoAsInt(Info::XMLVersionSubMinor, genApiVersion.SubMinor());
278 }
279
281
289 template <class T>
290 std::shared_ptr<T> Node(const String &name) const
291 {
292 static_assert(std::is_base_of<Cvb::GevServer::Node, T>::value, "requested node type must be derived from Node");
293 return std::dynamic_pointer_cast<T>(Node(name));
294 }
295
297
317 NodePtr Node(const String &name) const
318 {
319 auto nameOnly = GevServer::Node::ParseName(name);
320 if (nodes_.find(nameOnly) == nodes_.end())
321 throw std::out_of_range("no node for name");
322
323 auto node = nodes_[nameOnly];
324 if (!node)
325 {
326 node = Node::FromName(std::const_pointer_cast<NodeMap>(shared_from_this()), nameOnly);
327 nodes_[nameOnly] = node;
328 }
329
330 return node;
331 }
332
334
362 template <class T>
363 std::shared_ptr<T> TryGetNode(const String &name) const
364 {
365 static_assert(std::is_base_of<Cvb::GevServer::Node, T>::value, "requested node type must be derived from Node");
366 return std::dynamic_pointer_cast<T>(TryGetNode(name));
367 }
368
370
396 NodePtr TryGetNode(const String &name) const noexcept
397 {
398 NodePtr node = NodePtr();
399 try
400 {
401 node = Node(name);
402 }
403 catch (...)
404 {
405 }
406 return node;
407 }
408
409 private:
410 void FillNodeKeys();
411
412 std::string GetLastGSErrorMessage() const noexcept
413 {
414 std::size_t messageSize = 0;
415 auto res = CVB_CALL_CAPI(GSGetLastErrorString(nullptr, messageSize));
416 if (!res || messageSize < 2)
417 return {};
418 std::vector<char> message(messageSize);
419 if (CVB_CALL_CAPI(GSGetLastErrorString(message.data(), messageSize)))
420 return {};
421 return std::string(message.data());
422 }
423
424 void NativeCall(std::function<CExports::cvbres_t()> fn) const
425 {
426 auto result = fn();
427 if (result < 0)
428 {
429 auto message = GetLastGSErrorMessage();
430 if (message.empty())
431 message = "Error";
432
433 std::stringstream stream;
434 stream << "NodeMap: " << message;
435 std::rethrow_exception(CvbException::FromCvbResult(result, stream.str()));
436 }
437 }
438
439 template <class T>
440 T NativeCall(std::function<CExports::cvbres_t(T &value)> fn) const
441 {
442 T value;
443 auto result = fn(value);
444 if (result < 0)
445 {
446 auto message = Utilities::SystemInfo::GetLastErrorMessage();
447 if (message.empty())
448 message = "Error";
449
450 std::stringstream stream;
451 stream << "NodeMap: " << message;
452 std::rethrow_exception(CvbException::FromCvbResult(result, stream.str()));
453 }
454 return value;
455 }
456
457 std::int64_t GetInfoAsInt(Info command) const
458 {
459 return static_cast<std::int64_t>(NativeCall<CExports::cvbint64_t>([&](CExports::cvbint64_t &value) {
460 return CVB_CALL_CAPI(GSGetInfoAsInteger(Handle(), static_cast<CExports::TGSInfo>(command), value));
461 }));
462 }
463
464 void SetInfoAsInt(Info command, CExports::cvbint64_t value) const
465 {
466 NativeCall([&]() {
467 return CVB_CALL_CAPI(GSSetInfoAsInteger(Handle(), static_cast<CExports::TGSInfo>(command), value));
468 });
469 }
470
471 std::weak_ptr<class Server> server_;
472 mutable std::map<String, std::shared_ptr<class Node>> nodes_;
473 };
474 } // namespace GevServer
475 CVB_END_INLINE_NS
476} // namespace Cvb
std::shared_ptr< Node > NodePtr
Convenience shared pointer for Node.
Definition genapi.hpp:71
Namespace for GevServer based device configuration.
Definition decl_int_swiss_knife_node.hpp:11
std::shared_ptr< Server > ServerPtr
Convenience shared pointer for GevServer.
Definition gevserver.hpp:37
Root namespace for the Image Manager interface.
Definition c_bayer_to_rgb.h:17
std::string String
String for wide characters or unicode characters.
Definition string.hpp:49