Newer
Older
Martin Christoph Hierholzer
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* VariableNetworkNode.cc
*
* Created on: Jun 23, 2016
* Author: Martin Hierholzer
*/
#include <libxml++/libxml++.h>
#include "VariableNetworkNode.h"
#include "VariableNetwork.h"
#include "Accessor.h"
#include "Application.h"
namespace ChimeraTK {
/*********************************************************************************************************************/
bool VariableNetworkNode::hasImplementation() const {
return type == NodeType::Device || type == NodeType::ControlSystem;
}
/*********************************************************************************************************************/
void VariableNetworkNode::dump() const {
if(type == NodeType::Application) std::cout << " type = Application";
if(type == NodeType::ControlSystem) std::cout << " type = ControlSystem ('" << publicName << "')";
if(type == NodeType::Device) std::cout << " type = Device (" << deviceAlias << ": " << registerName << ")";
if(type == NodeType::TriggerReceiver) std::cout << " type = TriggerReceiver";
if(type == NodeType::invalid) std::cout << " type = **invalid**";
if(mode == UpdateMode::push) std::cout << " pushing" << std::endl;
if(mode == UpdateMode::poll) std::cout << " polling" << std::endl;
}
/*********************************************************************************************************************/
void VariableNetworkNode::createXML(xmlpp::Element *rootElement) const {
if(type != NodeType::ControlSystem) return;
// Create the directory for the path name in the XML document with all parent directories, if not yet existing:
// First split the publication name into components and loop over each component. For each component, try to find
// the directory node and create it it does not exist. After the loop, the "current" will point to the Element
// representing the directory.
// strip the variable name from the path
mtca4u::RegisterPath directory(publicName);
directory--;
// the namespace map is needed to properly refer to elements with an xpath expression in xmlpp::Element::find()
/// @todo TODO move this somewhere else, or at least take the namespace URI from a common place!
xmlpp::Node::PrefixNsMap nsMap{{"ac", "https://github.com/ChimeraTK/ApplicationCore"}};
// go through each directory path component
xmlpp::Element *current = rootElement;
for(auto pathComponent : directory.getComponents()) {
// find directory for this path component in the current directory
std::string xpath = std::string("ac:directory[@name='")+pathComponent+std::string("']");
auto list = current->find(xpath, nsMap);
if(list.size() == 0) { // not found: create it
xmlpp::Element *newChild = current->add_child("directory");
newChild->set_attribute("name",pathComponent);
current = newChild;
}
else {
assert(list.size() == 1);
current = dynamic_cast<xmlpp::Element*>(list[0]);
assert(current != nullptr);
}
}
// now add the variable to the directory
xmlpp::Element *variable = current->add_child("variable");
mtca4u::RegisterPath pathName(publicName);
auto pathComponents = pathName.getComponents();
// set the name attribute
variable->set_attribute("name",pathComponents[pathComponents.size()-1]);
// add sub-element containing the data type
std::string dataTypeName{"unknown"};
if(network->getValueType() == typeid(int8_t)) { dataTypeName = "int8"; }
else if(network->getValueType() == typeid(uint8_t)) { dataTypeName = "uint8"; }
else if(network->getValueType() == typeid(int16_t)) { dataTypeName = "int16"; }
else if(network->getValueType() == typeid(uint16_t)) { dataTypeName = "uint16"; }
else if(network->getValueType() == typeid(int32_t)) { dataTypeName = "int32"; }
else if(network->getValueType() == typeid(uint32_t)) { dataTypeName = "uint32"; }
else if(network->getValueType() == typeid(float)) { dataTypeName = "float"; }
else if(network->getValueType() == typeid(double)) { dataTypeName = "double"; }
else if(network->getValueType() == typeid(std::string)) { dataTypeName = "string"; }
xmlpp::Element *valueTypeElement = variable->add_child("value_type");
valueTypeElement->set_child_text(dataTypeName);
// add sub-element containing the data flow direction
std::string dataFlowName{"application_to_control_system"};
if(network->getFeedingNode() == *this) { dataFlowName = "control_system_to_application"; }
xmlpp::Element *directionElement = variable->add_child("direction");
directionElement->set_child_text(dataFlowName);
// add sub-element containing the engineering unit
xmlpp::Element *unitElement = variable->add_child("unit");
unitElement->set_child_text(network->getUnit());
}
/*********************************************************************************************************************/
bool VariableNetworkNode::operator==(const VariableNetworkNode& other) const {
if(other.network != network) return false;
if(other.type != type) return false;
if(other.mode != mode) return false;
if(other.appNode != appNode) return false;
if(other.publicName != publicName) return false;
if(other.deviceAlias != deviceAlias) return false;
if(other.registerName != registerName) return false;
return true;
}
/*********************************************************************************************************************/
bool VariableNetworkNode::operator!=(const VariableNetworkNode& other) const {
return !operator==(other);
}
}