-
Martin Christoph Hierholzer authoredMartin Christoph Hierholzer authored
VariableNetworkNode.cc 16.85 KiB
/*
* VariableNetworkNode.cc
*
* Created on: Jun 23, 2016
* Author: Martin Hierholzer
*/
#include "VariableNetworkNode.h"
#include "Application.h"
#include "EntityOwner.h"
#include "VariableNetwork.h"
#include "VariableNetworkNodeDumpingVisitor.h"
#include "Visitor.h"
namespace ChimeraTK {
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode(const VariableNetworkNode &other)
: pdata(other.pdata) {}
/*********************************************************************************************************************/
VariableNetworkNode &VariableNetworkNode::
operator=(const VariableNetworkNode &rightHandSide) {
pdata = rightHandSide.pdata;
return *this;
}
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode(
EntityOwner *owner, ChimeraTK::TransferElementAbstractor *accessorBridge,
const std::string &name, VariableDirection direction, std::string unit,
size_t nElements, UpdateMode mode, const std::string &description,
const std::type_info *valueType,
const std::unordered_set<std::string> &tags)
: pdata(boost::make_shared<VariableNetworkNode_data>()) {
pdata->owningModule = owner;
pdata->type = NodeType::Application;
pdata->appNode = accessorBridge;
pdata->name = name;
pdata->qualifiedName = owner->getQualifiedName() + "/" + name;
pdata->mode = mode;
pdata->direction = direction;
pdata->valueType = valueType;
pdata->unit = unit;
pdata->nElements = nElements;
pdata->description = description;
pdata->tags = tags;
}
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode(const std::string &name,
const std::string &devAlias,
const std::string ®Name,
UpdateMode mode, VariableDirection dir,
const std::type_info &valTyp,
size_t nElements)
: pdata(boost::make_shared<VariableNetworkNode_data>()) {
pdata->name = name;
pdata->type = NodeType::Device;
pdata->mode = mode;
pdata->direction = dir;
pdata->valueType = &valTyp;
pdata->deviceAlias = devAlias;
pdata->registerName = regName;
pdata->nElements = nElements;
}
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode(std::string pubName,
VariableDirection dir,
const std::type_info &valTyp,
size_t nElements)
: pdata(boost::make_shared<VariableNetworkNode_data>()) {
pdata->name = pubName;
pdata->type = NodeType::ControlSystem;
pdata->mode = UpdateMode::push;
pdata->direction = dir;
pdata->valueType = &valTyp;
pdata->publicName = pubName;
pdata->nElements = nElements;
}
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode(VariableNetworkNode &nodeToTrigger,
int)
: pdata(boost::make_shared<VariableNetworkNode_data>()) {
pdata->type = NodeType::TriggerReceiver;
pdata->direction = {VariableDirection::consuming, false};
pdata->nodeToTrigger = nodeToTrigger;
pdata->name = "trigger:" + nodeToTrigger.getName();
}
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode(
boost::shared_ptr<VariableNetworkNode_data> _pdata)
: pdata(_pdata) {}
/*********************************************************************************************************************/
VariableNetworkNode::VariableNetworkNode()
: pdata(boost::make_shared<VariableNetworkNode_data>()) {}
/*********************************************************************************************************************/
void VariableNetworkNode::setOwner(VariableNetwork *net) {
assert(pdata->network == nullptr);
assert(pdata->type != NodeType::invalid);
pdata->network = net;
}
/*********************************************************************************************************************/
void VariableNetworkNode::clearOwner() { pdata->network = nullptr; }
/*********************************************************************************************************************/
bool VariableNetworkNode::hasImplementation() const {
return pdata->type == NodeType::Device ||
pdata->type == NodeType::ControlSystem ||
pdata->type == NodeType::Constant;
}
/*********************************************************************************************************************/
void VariableNetworkNode::accept(Visitor<VariableNetworkNode> &visitor) const {
visitor.dispatch(*this);
}
/*********************************************************************************************************************/
bool VariableNetworkNode::operator==(const VariableNetworkNode &other) const {
return (other.pdata == pdata) || (pdata->type == NodeType::invalid &&
other.pdata->type == NodeType::invalid);
}
/*********************************************************************************************************************/
bool VariableNetworkNode::operator!=(const VariableNetworkNode &other) const {
return !operator==(other);
}
/*********************************************************************************************************************/
bool VariableNetworkNode::operator<(const VariableNetworkNode &other) const {
if (pdata->type == NodeType::invalid &&
other.pdata->type == NodeType::invalid)
return false;
return (other.pdata < pdata);
}
/*********************************************************************************************************************/
VariableNetworkNode VariableNetworkNode::operator>>(VariableNetworkNode other) {
if (pdata->direction.dir == VariableDirection::invalid) {
if (!other.hasOwner()) {
pdata->direction = {VariableDirection::feeding, false};
} else {
if (other.getOwner().hasFeedingNode()) {
pdata->direction = {VariableDirection::consuming, false};
if (getType() ==
NodeType::Device) { // special treatment for Device-type variables:
// consumers are push-type
pdata->mode = UpdateMode::push;
}
} else {
pdata->direction = {VariableDirection::feeding, false};
}
}
}
if (other.pdata->direction.dir == VariableDirection::invalid) {
if (!hasOwner()) {
other.pdata->direction = {VariableDirection::consuming, false};
if (other.getType() ==
NodeType::Device) { // special treatment for Device-type variables:
// consumers are push-type
other.pdata->mode = UpdateMode::push;
}
} else {
if (getOwner().hasFeedingNode()) {
other.pdata->direction = {VariableDirection::consuming, false};
if (other.getType() ==
NodeType::Device) { // special treatment for Device-type variables:
// consumers are push-type
other.pdata->mode = UpdateMode::push;
}
} else {
other.pdata->direction = {VariableDirection::feeding, false};
}
}
}
Application::getInstance().connect(*this, other);
return *this;
}
/*********************************************************************************************************************/
VariableNetworkNode VariableNetworkNode::
operator[](VariableNetworkNode trigger) {
// check if node already has a trigger
if (pdata->externalTrigger.getType() != NodeType::invalid) {
throw ChimeraTK::logic_error(
"Only one external trigger per variable network is allowed.");
}
// force direction of the node we are operating on to be feeding
if (pdata->direction.dir == VariableDirection::invalid)
pdata->direction = {VariableDirection::feeding, false};
assert(pdata->direction.dir == VariableDirection::feeding);
// force direction of the triggering node to be feeding
if (trigger.pdata->direction.dir == VariableDirection::invalid)
trigger.pdata->direction = {VariableDirection::feeding, false};
assert(trigger.pdata->direction.dir == VariableDirection::feeding);
// check if already existing in map
if (pdata->nodeWithTrigger.count(trigger) > 0) {
return pdata->nodeWithTrigger[trigger];
}
// create copy of the node
pdata->nodeWithTrigger[trigger].pdata =
boost::make_shared<VariableNetworkNode_data>(*pdata);
// add ourselves as a trigger receiver to the other network
if (!trigger.hasOwner()) {
Application::getInstance().createNetwork().addNode(trigger);
}
trigger.getOwner().addNodeToTrigger(pdata->nodeWithTrigger[trigger]);
// set flag and store pointer to other network
pdata->nodeWithTrigger[trigger].pdata->externalTrigger = trigger;
// return the new node
return pdata->nodeWithTrigger[trigger];
}
/*********************************************************************************************************************/
void VariableNetworkNode::setValueType(const std::type_info &newType) const {
assert(*pdata->valueType == typeid(AnyType));
pdata->valueType = &newType;
}
/*********************************************************************************************************************/
void VariableNetworkNode::setDirection(VariableDirection newDirection) const {
assert(pdata->type == NodeType::ControlSystem);
assert(pdata->direction.dir == VariableDirection::feeding);
pdata->direction = newDirection;
}
/*********************************************************************************************************************/
bool VariableNetworkNode::hasExternalTrigger() const {
return pdata->externalTrigger.getType() != NodeType::invalid;
}
/*********************************************************************************************************************/
VariableNetworkNode VariableNetworkNode::getExternalTrigger() {
assert(pdata->externalTrigger.getType() != NodeType::invalid);
return pdata->externalTrigger;
}
/*********************************************************************************************************************/
void VariableNetworkNode::dump(std::ostream &stream) const {
VariableNetworkNodeDumpingVisitor visitor(stream, " ");
visitor.dispatch(*this);
}
/*********************************************************************************************************************/
bool VariableNetworkNode::hasOwner() const { return pdata->network != nullptr; }
/*********************************************************************************************************************/
NodeType VariableNetworkNode::getType() const {
if (!pdata)
return NodeType::invalid;
return pdata->type;
}
/*********************************************************************************************************************/
UpdateMode VariableNetworkNode::getMode() const { return pdata->mode; }
/*********************************************************************************************************************/
VariableDirection VariableNetworkNode::getDirection() const {
return pdata->direction;
}
/*********************************************************************************************************************/
const std::type_info &VariableNetworkNode::getValueType() const {
return *(pdata->valueType);
}
/*********************************************************************************************************************/
std::string VariableNetworkNode::getName() const { return pdata->name; }
/*********************************************************************************************************************/
std::string VariableNetworkNode::getQualifiedName() const {
return pdata->qualifiedName;
}
/*********************************************************************************************************************/
const std::string &VariableNetworkNode::getUnit() const { return pdata->unit; }
/*********************************************************************************************************************/
const std::string &VariableNetworkNode::getDescription() const {
return pdata->description;
}
/*********************************************************************************************************************/
VariableNetwork &VariableNetworkNode::getOwner() const {
assert(pdata->network != nullptr);
return *(pdata->network);
}
/*********************************************************************************************************************/
VariableNetworkNode VariableNetworkNode::getNodeToTrigger() {
assert(pdata->nodeToTrigger.getType() != NodeType::invalid);
return pdata->nodeToTrigger;
}
/*********************************************************************************************************************/
const std::string &VariableNetworkNode::getPublicName() const {
assert(pdata->type == NodeType::ControlSystem);
return pdata->publicName;
}
/*********************************************************************************************************************/
const std::string &VariableNetworkNode::getDeviceAlias() const {
assert(pdata->type == NodeType::Device);
return pdata->deviceAlias;
}
/*********************************************************************************************************************/
const std::string &VariableNetworkNode::getRegisterName() const {
assert(pdata->type == NodeType::Device);
return pdata->registerName;
}
/*********************************************************************************************************************/
void VariableNetworkNode::setNumberOfElements(size_t nElements) {
pdata->nElements = nElements;
}
/*********************************************************************************************************************/
size_t VariableNetworkNode::getNumberOfElements() const {
return pdata->nElements;
}
/*********************************************************************************************************************/
ChimeraTK::TransferElementAbstractor &
VariableNetworkNode::getAppAccessorNoType() {
return *(pdata->appNode);
}
/*********************************************************************************************************************/
void VariableNetworkNode::setMetaData(const std::string &name,
const std::string &unit,
const std::string &description) {
if (getType() != NodeType::Application) {
throw ChimeraTK::logic_error(
"Calling VariableNetworkNode::updateMetaData() is not allowed for "
"non-application type nodes.");
}
pdata->name = name;
pdata->qualifiedName = pdata->owningModule->getQualifiedName() + "/" + name;
pdata->unit = unit;
pdata->description = description;
}
/*********************************************************************************************************************/
void VariableNetworkNode::setMetaData(
const std::string &name, const std::string &unit,
const std::string &description,
const std::unordered_set<std::string> &tags) {
setMetaData(name, unit, description);
pdata->tags = tags;
}
/*********************************************************************************************************************/
void VariableNetworkNode::addTag(const std::string &tag) {
pdata->tags.insert(tag);
}
/*********************************************************************************************************************/
const std::unordered_set<std::string> &VariableNetworkNode::getTags() const {
return pdata->tags;
}
/*********************************************************************************************************************/
void VariableNetworkNode::setAppAccessorPointer(
ChimeraTK::TransferElementAbstractor *accessor) {
assert(getType() == NodeType::Application);
pdata->appNode = accessor;
}
/*********************************************************************************************************************/
EntityOwner *VariableNetworkNode::getOwningModule() const {
return pdata->owningModule;
}
/*********************************************************************************************************************/
void VariableNetworkNode::setOwningModule(EntityOwner *newOwner) const {
pdata->owningModule = newOwner;
}
/*********************************************************************************************************************/
void VariableNetworkNode::setPublicName(const std::string &name) const {
pdata->publicName = name;
}
} // namespace ChimeraTK