Newer
Older
Martin Christoph Hierholzer
committed
/*
* EntityOwner.cc
*
* Created on: Nov 15, 2016
* Author: Martin Hierholzer
*/
#include <cassert>
#include <regex>
Martin Christoph Hierholzer
committed
#include <iostream>
#include "EntityOwner.h"
#include "Module.h"
Martin Christoph Hierholzer
committed
#include "VirtualModule.h"
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
EntityOwner::EntityOwner(const std::string &name, const std::string &description,
bool eliminateHierarchy, const std::unordered_set<std::string> &tags)
: _name(name), _description(description), _eliminateHierarchy(eliminateHierarchy), _tags(tags)
{}
/*********************************************************************************************************************/
EntityOwner::~EntityOwner() {}
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
EntityOwner::EntityOwner(EntityOwner &&other)
: _name(std::move(other._name)),
_description(std::move(other._description)),
accessorList(std::move(other.accessorList)),
moduleList(std::move(other.moduleList)),
_eliminateHierarchy(other._eliminateHierarchy),
_tags(std::move(other._tags))
{
for(auto mod : moduleList) {
mod->setOwner(this);
}
for(auto node : accessorList) {
node.setOwningModule(this);
Martin Christoph Hierholzer
committed
}
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
void EntityOwner::registerModule(Module *module, bool addTags) {
if(addTags) for(auto &tag : _tags) module->addTag(tag);
Martin Christoph Hierholzer
committed
moduleList.push_back(module);
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
void EntityOwner::unregisterModule(Module *module) {
moduleList.remove(module);
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
std::list<VariableNetworkNode> EntityOwner::getAccessorListRecursive() {
Martin Christoph Hierholzer
committed
// add accessors of this instance itself
Martin Christoph Hierholzer
committed
std::list<VariableNetworkNode> list = getAccessorList();
Martin Christoph Hierholzer
committed
// iterate through submodules
for(auto submodule : getSubmoduleList()) {
Martin Christoph Hierholzer
committed
auto sublist = submodule->getAccessorListRecursive();
Martin Christoph Hierholzer
committed
list.insert(list.end(), sublist.begin(), sublist.end());
}
return list;
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
std::list<Module*> EntityOwner::getSubmoduleListRecursive() {
// add modules of this instance itself
std::list<Module*> list = getSubmoduleList();
// iterate through submodules
for(auto submodule : getSubmoduleList()) {
auto sublist = submodule->getSubmoduleListRecursive();
list.insert(list.end(), sublist.begin(), sublist.end());
}
return list;
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
VirtualModule EntityOwner::findTag(const std::string &tag) const {
Martin Christoph Hierholzer
committed
// create new module to return
VirtualModule module{_name, _description, getModuleType()};
Martin Christoph Hierholzer
committed
// add everything matching the tag to the virtual module and return it
findTagAndAppendToModule(module, tag, false, true);
Martin Christoph Hierholzer
committed
return module;
}
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
VirtualModule EntityOwner::excludeTag(const std::string &tag) const {
// create new module to return
VirtualModule module{_name, _description, getModuleType()};
Martin Christoph Hierholzer
committed
// add everything matching the tag to the virtual module and return it
findTagAndAppendToModule(module, tag, false, true, true);
return module;
}
/*********************************************************************************************************************/
void EntityOwner::findTagAndAppendToModule(VirtualModule &module, const std::string &tag, bool eliminateAllHierarchies,
bool eliminateFirstHierarchy, bool negate) const {
VirtualModule nextmodule{_name, _description, getModuleType()};
Martin Christoph Hierholzer
committed
VirtualModule *moduleToAddTo;
bool needToAddSubModule = false;
Martin Christoph Hierholzer
committed
if(!getEliminateHierarchy() && !eliminateAllHierarchies && !eliminateFirstHierarchy) {
moduleToAddTo = &nextmodule;
needToAddSubModule = true;
Martin Christoph Hierholzer
committed
}
else {
moduleToAddTo = &module;
}
// add nodes to the module if matching the tag
std::regex expr(tag);
Martin Christoph Hierholzer
committed
for(auto node : getAccessorList()) {
bool addNode = false;
for(auto &nodeTag : node.getTags()) {
if(std::regex_match(nodeTag, expr)) {
addNode = true;
break;
}
Martin Christoph Hierholzer
committed
}
if(node.getTags().size() == 0) if(std::regex_match("", expr)) addNode = true; // check if empty tag matches, if no tag applied to node
if(negate) addNode = !addNode;
if(addNode) moduleToAddTo->registerAccessor(node);
Martin Christoph Hierholzer
committed
}
// iterate through submodules
for(auto submodule : getSubmoduleList()) {
submodule->findTagAndAppendToModule(*moduleToAddTo, tag, eliminateAllHierarchies, false, negate);
Martin Christoph Hierholzer
committed
}
if(needToAddSubModule) {
if( nextmodule.getAccessorList().size() > 0 || nextmodule.getSubmoduleList().size() > 0 ) {
module.addSubModule(nextmodule);
}
}
Martin Christoph Hierholzer
committed
}
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
void EntityOwner::dump(const std::string &prefix) const {
if(prefix == "") {
std::cout << "==== Hierarchy dump of module '" << _name << "':" << std::endl;
}
for(auto &node : getAccessorList()) {
Martin Christoph Hierholzer
committed
std::cout << prefix << "+ ";
node.dump();
}
for(auto &submodule : getSubmoduleList()) {
Martin Christoph Hierholzer
committed
std::cout << prefix << "| " << submodule->getName() << std::endl;
submodule->dump(prefix+"| ");
}
}
/*********************************************************************************************************************/
void EntityOwner::dumpGraph(const std::string& fileName) const {
std::fstream file(fileName, std::ios_base::out);
file << "digraph G {" << std::endl;
dumpGraphInternal(file, true);
file << "}" << std::endl;
file.close();
}
/*********************************************************************************************************************/
void EntityOwner::dumpModuleGraph(const std::string& fileName) const {
std::fstream file(fileName, std::ios_base::out);
file << "digraph G {" << std::endl;
dumpGraphInternal(file, false);
file << "}" << std::endl;
file.close();
/*********************************************************************************************************************/
std::string EntityOwner::cleanDotNode(std::string fullName) const {
std::replace(fullName.begin(), fullName.end(), '/', '_');
std::replace(fullName.begin(), fullName.end(), ':', '_');
return fullName;
}
/*********************************************************************************************************************/
void EntityOwner::dumpGraphInternal(std::ostream &stream, bool showVariables) const {
std::string myDotNode = cleanDotNode(getQualifiedName());
stream << myDotNode << "[label=\"" << getName() << "\"";
if(_eliminateHierarchy) {
stream << ",style=dotted";
}
if(getModuleType() == ModuleType::ModuleGroup) {
stream << ",peripheries=2";
}
if(getModuleType() == ModuleType::ApplicationModule) {
stream << ",style=bold";
}
stream << "]" << std::endl;
if(showVariables) {
for(auto &node : getAccessorList()) {
std::string dotNode = cleanDotNode(node.getQualifiedName());
stream << dotNode << "[label=\"{" << node.getName() << "| {";
bool first = true;
for(auto tag : node.getTags()) {
if(!first) {
stream << "|";
}
else {
first = false;
}
stream << tag;
}
stream << "}}\", shape=record]" << std::endl;
stream << " " << myDotNode << " -> " << dotNode << std::endl;
}
}
for(auto submodule : getSubmoduleList()) {
if(submodule->getModuleType() == ModuleType::Device ||
submodule->getModuleType() == ModuleType::ControlSystem) continue;
std::string dotNode = cleanDotNode(submodule->getQualifiedName());
stream << " " << myDotNode << " -> " << dotNode << std::endl;
submodule->dumpGraphInternal(stream, showVariables);
}
}
/*********************************************************************************************************************/
void EntityOwner::addTag(const std::string &tag) {
for(auto &node : getAccessorList()) node.addTag(tag);
for(auto &submodule : getSubmoduleList()) submodule->addTag(tag);
_tags.insert(tag);
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
VirtualModule EntityOwner::flatten() {
VirtualModule nextmodule{_name, _description, getModuleType()};
Martin Christoph Hierholzer
committed
for(auto &node : getAccessorListRecursive()) {
Martin Christoph Hierholzer
committed
nextmodule.registerAccessor(node);
}
return nextmodule;
}
Martin Christoph Hierholzer
committed
Martin Christoph Hierholzer
committed
} /* namespace ChimeraTK */