Rosetta
|
A data map designed to help create hierarchies with complicated shared data requirements. More...
#include <HierarchicalDataMap.hh>
Public Member Functions | |
HierarchicalDataMap () | |
Default constructor. More... | |
~HierarchicalDataMap () override | |
Default destructor. More... | |
void | set_parent (HierarchicalDataMapCAP parent) |
Set a parent for this data map. More... | |
void | unset_parent () |
Unset the parent for this data map. More... | |
template<typename ValueOP > | |
ValueOP | get (std::string const &type, std::string const &name) const |
Return the value associated with the given key. If the key is not found, throw an exception. More... | |
template<typename ValueOP > | |
ValueOP | get (std::string const &type, std::string const &name, ValueOP fallback) const |
Return the value associated with the given key. If the key is not found, return the given fallback value. More... | |
template<typename ValueOP > | |
ValueOP | get_or_null (std::string const &type, std::string const &name) const |
Return the value associated with the given key. If the key is not found, return a null owning pointer. More... | |
template<typename ValueOP > | |
ValueOP | set (std::string const &type, std::string const &name, ValueOP value) |
Set the value of the given key in this map. This value may also be accessed by children maps. More... | |
![]() | |
VirtualBase ()=default | |
Default constructor. More... | |
virtual | ~VirtualBase ()=default |
The virtual destructor is one of the main reasons for the VirtualBase class. More... | |
VirtualBase (VirtualBase const &)=default | |
VirtualBase (VirtualBase &&)=default | |
VirtualBase & | operator= (VirtualBase const &)=default |
VirtualBase & | operator= (VirtualBase &&)=default |
Private Attributes | |
HierarchicalDataMapCAP | parent_ |
DataMap | data_map_ |
A data map designed to help create hierarchies with complicated shared data requirements.
To explain what exactly this class is supposed to do, consider the following mover hierarchy (which comes from the loop modeling framework and was the actual motivation for this code):
A ~ | ~ +-------+------+------+------+ ~ | | | | | ~ B C D E F ~ / \ / \ / \ ~ G H I J K L ~ | | / /|\ ~ M N O P Q R ~
To explain this diagram a little, each letter corresponds to a mover. The movers are mostly of different classes, although they all inherit from the same abstract base class. This whole hierarchy is constructed by A. When A.apply() is called, it calls B.apply(), C.apply(), D.apply(), E.apply(), and F.apply() in that order. When B.apply() is called, it calls G.apply() and H.apply(), and so on. If you are interested in seeing exactly how this hierarchy is implemented, here are the classes the letters correspond to:
A. protocols::loop_modeling::LoopModeler B. protocols::loop_modeling::utilities::PrepareForCentroid C. protocols::loop_modeling::LoopBuilder D. protocols::loop_modeling::LoopProtocol E. protocols::loop_modeling::utilities::PrepareForFullatom F. protocols::loop_modeling::LoopProtocol G. protocols::kinematic_closure::KicMover H. protocols::loop_modeling::refiners::MinimizationRefiner I. protocols::loop_modeling::utilities::LoopMoverGroup J. protocols::loop_modeling::utilities::LoopMoverGroup K. protocols::loop_modeling::utilities::LoopMoverGroup L. protocols::loop_modeling::utilities::LoopMoverGroup M. protocols::kinematic_closure::KicMover N. protocols::loop_modeling::refiners::MinimizationRefiner O. protocols::kinematic_closure::KicMover P. protocols::loop_modeling::refiners::RepackingRefiner Q. protocols::loop_modeling::refiners::RotamerTrialsRefiner R. protocols::loop_modeling::refiners::MinimizationRefiner
This hierarchy had the following shared data requirements:
Many of these requirements have a similar form: movers higher in the hierarchy must be able to provide default attributes to all their children, and movers lower in the hierarchy must be able to override those defaults. This class supports that pattern by being a data map that asks its parent for missing values.
More specifically, this class stores two pieces of information: a DataMap and a pointer to a parent HierarchicalDataMap. The DataMap provides the basic attribute lookup capability: it's just a string to owning pointer map. The parent pointer allows the HierarchicalDataMap to recursively access default values from parent maps for key that aren't in it's own DataMap.
Going back to the example hierarchy above: A needs to provide a default task factory that P and Q can override. To accomplish this, we start by giving all the objects in the hierarchy HierarchicalDataMap objects that have been properly connected to their parents. Then A sets the default "task_ops" attribute in it's own HierarchicalDataMap as soon as it's constructed. P and Q provide convenience methods like get_task_ops() and set_task_ops() to allow the "task_ops" field of their HierarchicalDataMaps to be accessed publicly. Since the data maps in P and Q are connected to A via L and F, the attributes stored in A will serve as defaults for P and Q.
It's worth noting that in this example, it is also possible to get the right behavior by putting a task operations data member in the shared base class. However, this is a poor solution for two reasons. The first is that it requires many classes that have no need for task operations to have a task operations attribute. Second, it requires that you write the default logic for each attribute that needs it, which is a duplication of effort. Using HierarchicalDataMap addresses both of these problems.
When using this class to help build a hierarchy like the one illustrated above, you might find it useful to move public accessor methods (like get_task_ops() and set_task_ops() in P and Q) into a reusable mixin class. This takes a little bit of C++ template magic, because you have to use the "curiously recurring template pattern" (CRTP). But you can see how this works by looking at protocols::loop_modeling::RepackingLoopMover (P in the example) and protocols::loop_modeling::utilites::TaskFactoryMixin (the mixin class).
|
default |
Default constructor.
|
overridedefault |
Default destructor.
|
inline |
Return the value associated with the given key. If the key is not found, throw an exception.
The key is first searched for in this data map, and then subsequently in parent data maps. The first key that is found is returned. The key is composed of a type and a name. Furthermore, the name "" is handled specially: it matches any name that's not already in the data map. For example, consider a data map with the following keys: ("spam", "") and ("spam", "eggs"). If you request ("spam", "bacon"), the value associated with ("spam", "") will be returned. If ("spam", "") hadn't been present, ("spam", "bacon") wouldn't have been found and the search would have continued.
References CREATE_EXCEPTION, pyrosetta.utility.array::message, and value.
|
inline |
Return the value associated with the given key. If the key is not found, return the given fallback value.
The key is first searched for in this data map, and then subsequently in parent data maps. The first key that is found is returned. The key is composed of a type and a name. Furthermore, the name "" is handled specially: it matches any name that's not already in the data map. For example, consider a data map with the following keys: ("spam", "") and ("spam", "eggs"). If you request ("spam", "bacon"), the value associated with ("spam", "") will be returned. If ("spam", "") hadn't been present, ("spam", "bacon") wouldn't have been found and the search would have continued.
References data_map_, basic::datacache::DataMap::get_ptr(), basic::datacache::DataMap::has(), and parent_.
|
inline |
Return the value associated with the given key. If the key is not found, return a null owning pointer.
The key is first searched for in this data map, and then subsequently in parent data maps. The first key that is found is returned. The key is composed of a type and a name. Furthermore, the name "" is handled specially: it matches any name that's not already in the data map. For example, consider a data map with the following keys: ("spam", "") and ("spam", "eggs"). If you request ("spam", "bacon"), the value associated with ("spam", "") will be returned. If ("spam", "") hadn't been present, ("spam", "bacon") wouldn't have been found and the search would have continued.
|
inline |
void basic::datacache::HierarchicalDataMap::set_parent | ( | HierarchicalDataMapCAP | parent | ) |
Set a parent for this data map.
If a key is requested and not found in this data map, the search will continue (recursively) in the parent. Having a parent is optional.
References parent_.
void basic::datacache::HierarchicalDataMap::unset_parent | ( | ) |
Unset the parent for this data map.
When a data map doesn't have a parent, it will only return keys it is holding itself. Having a parent is optional.
References parent_.
|
private |
Referenced by get(), set_parent(), and unset_parent().