Skip to content
Snippets Groups Projects
Commit 3a39b81f authored by Martin Christoph Hierholzer's avatar Martin Christoph Hierholzer
Browse files

added preliminary support for tags to application variables which can be...

added preliminary support for tags to application variables which can be searched for and used to generate virtual modules
parent df8a98a8
No related branches found
No related tags found
No related merge requests found
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "DeviceModule.h" #include "DeviceModule.h"
#include "ControlSystemModule.h" #include "ControlSystemModule.h"
#include "VariableGroup.h" #include "VariableGroup.h"
#include "VirtualModule.h"
#ifndef CHIMERATK_APPLICATION_CORE_H #ifndef CHIMERATK_APPLICATION_CORE_H
#define CHIMERATK_APPLICATION_CORE_H #define CHIMERATK_APPLICATION_CORE_H
......
...@@ -24,6 +24,11 @@ namespace ChimeraTK { ...@@ -24,6 +24,11 @@ namespace ChimeraTK {
template< typename UserType > template< typename UserType >
class ArrayAccessor : public mtca4u::OneDRegisterAccessor<UserType> { class ArrayAccessor : public mtca4u::OneDRegisterAccessor<UserType> {
public: public:
/** Change meta data (name, unit, description) */
void setMetaData(const std::string &name, const std::string &unit, const std::string &description) {
node.setMetaData(name,unit,description);
}
/** Convert into VariableNetworkNode */ /** Convert into VariableNetworkNode */
operator VariableNetworkNode() { operator VariableNetworkNode() {
...@@ -66,6 +71,12 @@ namespace ChimeraTK { ...@@ -66,6 +71,12 @@ namespace ChimeraTK {
if(_owner != nullptr) _owner->unregisterAccessor(*this); if(_owner != nullptr) _owner->unregisterAccessor(*this);
} }
/** Add a tag. Valid names for tags only contain alpha-numeric characters (i.e. no spaces and no special
* characters). */
void addTag(const std::string &tag) {
node.addTag(tag);
}
protected: protected:
ArrayAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit, ArrayAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit,
size_t nElements, UpdateMode mode, const std::string &description) size_t nElements, UpdateMode mode, const std::string &description)
......
...@@ -17,6 +17,7 @@ namespace ChimeraTK { ...@@ -17,6 +17,7 @@ namespace ChimeraTK {
class AccessorBase; class AccessorBase;
class Module; class Module;
class VirtualModule;
/** Base class for owners of other EntityOwners (e.g. Modules) and Accessors. /** Base class for owners of other EntityOwners (e.g. Modules) and Accessors.
* @todo Rename this class to "Owner" and make it more generic. It should basically just implement the * @todo Rename this class to "Owner" and make it more generic. It should basically just implement the
...@@ -38,6 +39,7 @@ namespace ChimeraTK { ...@@ -38,6 +39,7 @@ namespace ChimeraTK {
/** Obtain the list of accessors/variables directly associated with this instance */ /** Obtain the list of accessors/variables directly associated with this instance */
std::list<VariableNetworkNode>& getAccessorList() { return accessorList; } std::list<VariableNetworkNode>& getAccessorList() { return accessorList; }
const std::list<VariableNetworkNode>& getAccessorList() const { return accessorList; }
/** Obtain the list of submodules associated with this instance */ /** Obtain the list of submodules associated with this instance */
const std::list<Module*>& getSubmoduleList() const { return moduleList; } const std::list<Module*>& getSubmoduleList() const { return moduleList; }
...@@ -47,6 +49,16 @@ namespace ChimeraTK { ...@@ -47,6 +49,16 @@ namespace ChimeraTK {
/** Obtain the list of submodules associated with this instance and any submodules */ /** Obtain the list of submodules associated with this instance and any submodules */
std::list<Module*> getSubmoduleListRecursive(); std::list<Module*> getSubmoduleListRecursive();
/** Return a VirtualModule containing the part of the tree structure matching the given tag. The resulting
* VirtualModule might have virtual sub-modules, if this EntityOwner contains sub-EntityOwners with
* entities matchting the tag. */
VirtualModule findTag(const std::string &tag, bool eliminateAllHierarchies=false) const;
/** Add the part of the tree structure matching the given tag to a VirtualModule. Users normally will use
* findTag() instead. */
void findTagAndAppendToModule(VirtualModule &module, const std::string &tag, bool eliminateAllHierarchies=false,
bool eliminateFirstHierarchy=false) const;
/** Called inside the constructor of Accessor: adds the accessor to the list */ /** Called inside the constructor of Accessor: adds the accessor to the list */
void registerAccessor(VariableNetworkNode accessor) { void registerAccessor(VariableNetworkNode accessor) {
...@@ -63,6 +75,21 @@ namespace ChimeraTK { ...@@ -63,6 +75,21 @@ namespace ChimeraTK {
/** Unregister another module as a sub-mdoule. Will be called automatically by all modules in their destructors. */ /** Unregister another module as a sub-mdoule. Will be called automatically by all modules in their destructors. */
void unregisterModule(Module* module); void unregisterModule(Module* module);
/** Eliminate the level of hierarchy represented by this EntityOwner. This is e.g. used when building the
* hierarchy of VirtualModules in findTag(). Eliminating one level of hierarchy will make all childs of that
* hierarchy level to appear as if there were direct childs of the next higher hierarchy level. If e.g. there is
* a variable on the third level "A.B.C" and one selects to eliminate the second level of hierarchy (e.g. calls
* B.eliminateHierarchy()), the structure would look like "A.C". This of course only affects the "dynamic" data
* model, while the static C++ model is fixed at compile time.
* @todo Also use in VariableGroup::operator() and VariableGroup::operator[] ??? */
void eliminateHierarchy() { _eliminateHierarchy = true; }
/** Returns the flag whether this level of hierarchy should be eliminated */
bool getEliminateHierarchy() const { return _eliminateHierarchy; }
/** Print the full hierarchy to stdout. */
void dump(const std::string &prefix="") const;
protected: protected:
...@@ -78,6 +105,9 @@ namespace ChimeraTK { ...@@ -78,6 +105,9 @@ namespace ChimeraTK {
/** List of modules owned by this instance */ /** List of modules owned by this instance */
std::list<Module*> moduleList; std::list<Module*> moduleList;
/** Flag whether this level of hierarchy should be eliminated or not */
bool _eliminateHierarchy{false};
}; };
} /* namespace ChimeraTK */ } /* namespace ChimeraTK */
......
...@@ -25,6 +25,11 @@ namespace ChimeraTK { ...@@ -25,6 +25,11 @@ namespace ChimeraTK {
template< typename UserType > template< typename UserType >
class ScalarAccessor : public mtca4u::ScalarRegisterAccessor<UserType> { class ScalarAccessor : public mtca4u::ScalarRegisterAccessor<UserType> {
public: public:
/** Change meta data (name, unit, description) */
void setMetaData(const std::string &name, const std::string &unit, const std::string &description) {
node.setMetaData(name,unit,description);
}
/** Convert into VariableNetworkNode */ /** Convert into VariableNetworkNode */
operator VariableNetworkNode() { operator VariableNetworkNode() {
...@@ -66,6 +71,12 @@ namespace ChimeraTK { ...@@ -66,6 +71,12 @@ namespace ChimeraTK {
if(_owner != nullptr) _owner->unregisterAccessor(*this); if(_owner != nullptr) _owner->unregisterAccessor(*this);
} }
/** Add a tag. Valid names for tags only contain alpha-numeric characters (i.e. no spaces and no special
* characters). */
void addTag(const std::string &tag) {
node.addTag(tag);
}
protected: protected:
ScalarAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit, ScalarAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit,
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#ifndef CHIMERATK_VARIABLE_NETWORK_NODE_H #ifndef CHIMERATK_VARIABLE_NETWORK_NODE_H
#define CHIMERATK_VARIABLE_NETWORK_NODE_H #define CHIMERATK_VARIABLE_NETWORK_NODE_H
#include <unordered_set>
#include <assert.h> #include <assert.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
...@@ -64,6 +66,9 @@ namespace ChimeraTK { ...@@ -64,6 +66,9 @@ namespace ChimeraTK {
/** Factory function for a constant (a constructor cannot be templated) */ /** Factory function for a constant (a constructor cannot be templated) */
template<typename UserType> template<typename UserType>
static VariableNetworkNode makeConstant(bool makeFeeder, UserType value=0, size_t length=1); static VariableNetworkNode makeConstant(bool makeFeeder, UserType value=0, size_t length=1);
/** Change meta data (name, unit, description). This function may only be used on Application-type nodes. */
void setMetaData(const std::string &name, const std::string &unit, const std::string &description);
/** Set the owner network of this node. If an owner network is already set, an assertion will be raised */ /** Set the owner network of this node. If an owner network is already set, an assertion will be raised */
void setOwner(VariableNetwork *network); void setOwner(VariableNetwork *network);
...@@ -102,6 +107,10 @@ namespace ChimeraTK { ...@@ -102,6 +107,10 @@ namespace ChimeraTK {
/** Check if the node already has an owner */ /** Check if the node already has an owner */
bool hasOwner() const; bool hasOwner() const;
/** Add a tag. This function may only be used on Application-type nodes. Valid names for tags only contain
* alpha-numeric characters (i.e. no spaces and no special characters). @todo enforce this!*/
void addTag(const std::string &tag);
/** Getter for the properties */ /** Getter for the properties */
NodeType getType() const; NodeType getType() const;
...@@ -116,6 +125,7 @@ namespace ChimeraTK { ...@@ -116,6 +125,7 @@ namespace ChimeraTK {
const std::string& getPublicName() const; const std::string& getPublicName() const;
const std::string& getDeviceAlias() const; const std::string& getDeviceAlias() const;
const std::string& getRegisterName() const; const std::string& getRegisterName() const;
const std::unordered_set<std::string>& getTags() const;
void setNumberOfElements(size_t nElements); void setNumberOfElements(size_t nElements);
size_t getNumberOfElements() const; size_t getNumberOfElements() const;
mtca4u::TransferElement& getAppAccessorNoType(); mtca4u::TransferElement& getAppAccessorNoType();
...@@ -190,6 +200,9 @@ namespace ChimeraTK { ...@@ -190,6 +200,9 @@ namespace ChimeraTK {
/** Number of elements in the variable. 0 means not yet decided. */ /** Number of elements in the variable. 0 means not yet decided. */
size_t nElements{0}; size_t nElements{0};
/** Set of tags if type == Application */
std::unordered_set<std::string> tags;
}; };
......
/*
* VirtualModule.h
*
* Created on: Apr 4, 2017
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_VIRTUAL_MODULE_H
#define CHIMERATK_VIRTUAL_MODULE_H
#include <list>
#include <boost/thread.hpp>
#include "Module.h"
namespace ChimeraTK {
/** A virtual module generated by EntityOwner::findTag(). */
class VirtualModule : public Module {
public:
/** Constructor */
VirtualModule(const std::string &name) : Module(nullptr, name) {}
/** Destructor */
virtual ~VirtualModule();
VariableNetworkNode operator()(const std::string& variableName);
Module& operator[](const std::string& moduleName);
/** Add a virtual sub-module. The module instance will be added to an internal list. */
void addSubModule(const VirtualModule &module);
protected:
std::list<VirtualModule> submodules;
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_VIRTUAL_MODULE_H */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "EntityOwner.h" #include "EntityOwner.h"
#include "Module.h" #include "Module.h"
#include "VirtualModule.h"
namespace ChimeraTK { namespace ChimeraTK {
...@@ -71,5 +72,67 @@ namespace ChimeraTK { ...@@ -71,5 +72,67 @@ namespace ChimeraTK {
} }
return list; return list;
} }
/*********************************************************************************************************************/
VirtualModule EntityOwner::findTag(const std::string &tag, bool eliminateAllHierarchies) const {
// create new module to return
VirtualModule module{_name+"{"+tag+"}"};
// add everything matching the tag to the virtual module and return it
findTagAndAppendToModule(module, tag, eliminateAllHierarchies, true);
return module;
}
/*********************************************************************************************************************/
void EntityOwner::findTagAndAppendToModule(VirtualModule &module, const std::string &tag, bool eliminateAllHierarchies,
bool eliminateFirstHierarchy) const {
VirtualModule nextmodule{_name+"{"+tag+"}"};
VirtualModule *moduleToAddTo;
if(!getEliminateHierarchy() && !eliminateAllHierarchies && !eliminateFirstHierarchy) {
moduleToAddTo = &nextmodule;
module.addSubModule(nextmodule);
}
else {
moduleToAddTo = &module;
}
// add nodes to the module if matching the tag
for(auto node : getAccessorList()) {
if(node.getTags().count(tag) > 0) {
moduleToAddTo->registerAccessor(node);
}
}
// iterate through submodules
for(auto submodule : getSubmoduleList()) {
submodule->findTagAndAppendToModule(*moduleToAddTo, tag, eliminateAllHierarchies);
}
}
/*********************************************************************************************************************/
void EntityOwner::dump(const std::string &prefix) const {
if(prefix == "") {
std::cout << "==== Hierarchy dump of module '" << _name << "':" << std::endl;
}
for(auto node : getAccessorList()) {
std::cout << prefix << "+ ";
node.dump();
}
for(auto submodule : getSubmoduleList()) {
std::cout << prefix << "| " << submodule->getName() << std::endl;
submodule->dump(prefix+"| ");
}
}
} /* namespace ChimeraTK */ } /* namespace ChimeraTK */
...@@ -396,4 +396,29 @@ namespace ChimeraTK { ...@@ -396,4 +396,29 @@ namespace ChimeraTK {
return *(pdata->appNode); return *(pdata->appNode);
} }
/*********************************************************************************************************************/
void VariableNetworkNode::setMetaData(const std::string &name, const std::string &unit,
const std::string &description) {
if(getType() != NodeType::Application) {
throw ApplicationExceptionWithID<ApplicationExceptionID::illegalParameter>(
"Calling VariableNetworkNode::updateMetaData() is not allowed for non-application type nodes.");
}
pdata->name = name;
pdata->unit = unit;
pdata->description = description;
}
/*********************************************************************************************************************/
void VariableNetworkNode::addTag(const std::string &tag) {
pdata->tags.insert(tag);
}
/*********************************************************************************************************************/
const std::unordered_set<std::string>& VariableNetworkNode::getTags() const {
return pdata->tags;
}
} }
/*
* VirtualModule.cc
*
* Created on: Apr 4, 2017
* Author: Martin Hierholzer
*/
#include <mtca4u/TransferElement.h>
#include "Application.h"
#include "VirtualModule.h"
namespace ChimeraTK {
VirtualModule::~VirtualModule() {
}
/*********************************************************************************************************************/
VariableNetworkNode VirtualModule::operator()(const std::string& variableName) {
for(auto variable : getAccessorList()) {
if(variable.getName() == variableName) return VariableNetworkNode(variable);
}
throw std::logic_error("Variable '"+variableName+"' is not part of the variable group '"+_name+"'.");
}
/*********************************************************************************************************************/
Module& VirtualModule::operator[](const std::string& moduleName) {
for(auto submodule : getSubmoduleList()) {
if(submodule->getName() == moduleName) return *submodule;
}
throw std::logic_error("Sub-module '"+moduleName+"' is not part of the variable group '"+_name+"'.");
}
/*********************************************************************************************************************/
void VirtualModule::addSubModule(const VirtualModule &module) {
submodules.push_back(module);
registerModule(&(submodules.back()));
}
} /* namespace ChimeraTK */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment