ARON Visitors

Visitors are a useful tool to define specific methods for specific types without specifying the switch(): case: ... again and again. Further, recursive visitors offer a convenient way to iterate through the tree-like structure of any Aron object. (Please note that right now the implementation does not check for cycles!). Again, we will only look at data visitors since the implementation of type visitors is more or less similar.

Non-recursive Visitors

First, there are "normal" visitors. They are used to get rid of the big switch-case statement when getting an Aron object with unknown type. Further, these visitors can be used to convert an Aron object from one representation into another (see ARON Readers, Writers and Conversion). The armarx::aron::data::Visitor base class offers the following pure virtual methods which you have to implement:

virtual data::Descriptor getDescriptor(Input&) = 0;
virtual void visitDict(Input&) {};
virtual void visitList(Input&) {};
virtual void visitNDArray(Input&) {};
virtual void visitInt(Input&) {};
virtual void visitLong(Input&) {};
virtual void visitFloat(Input&) {};
virtual void visitDouble(Input&) {};
virtual void visitBool(Input&) {};
virtual void visitString(Input&) {};
virtual void visitUnknown(Input&) { throw error::AronException(__PRETTY_FUNCTION__, "Unknown type in visitor."); }

Input is a template parameter, defining the Input-type (e.g. const armarx::aron::data::VariantPtr for a VariantVisitor Implementation).

The method getDescriptor(Input&) is used for the switch case internally.

As you can see the VariantVisitor always gets a generic variant as input in each function. This means that, although the Visitor guarantees that the input is correct, you have to cast the class to the correct type. For widely used Visitors, the Aron library offers convenience implementations (e.g. for Variants and for nlohmann::json inputs). The convenience class for Variants additionally adds overloads where the input is already cast correctly (you can decide which method you want to override).

To use a Visitor, you have to use the function

void visit(VisitorImplementation& v, typename VisitorImplementation::Input& o);

which takes the visitor and the input as arguments and does the switch-case.

Recursive Visitors

Recursive visitors are similar to normal visitors, but they continue "visiting" until the object is fully visited. For containers (e.g. dicts, lists) they offer two methods each:

virtual void visitDictOnEnter(Input& element) {};
virtual void visitDictOnExit(Input& element) {};
virtual void visitListOnEnter(Input& element) {};
virtual void visitListOnExit(Input& element) {};

The *OnEnter method is called before iterating over all children of the container. The *OnExit is called after the iteration.

Further, in order to get the elements of a container, you must implement the methods:

virtual MapElements getDictElements(Input&) = 0;
virtual ListElements getListElements(Input&) = 0;

Again, Input can be any aron object (e.g. Variant or nlohmann::json).

As for normal visitors, the Aron library offers convenience implementations for Variants and nlohmann::json inputs.

To use the RecursiveVisitor, you have to use the function

void visitRecursive(RecursiveVisitorImplementation& v, typename RecursiveVisitorImplementation::Input& o);

Example

Assume you want to count how many objects of each kind you have in a Variant.

class CountingRecursiveVisitor : public RecursiveConstVariantVisitor
{
public:
int dicts = 0;
int lists = 0;
int ndarrays = 0;
int ints = 0;
int floats = 0;
int longs = 0;
int doubles = 0;
int strings = 0;
int bools = 0;
public:
void visitAronVariantOnEnter(const data::DictPtr&) override { dicts++; }
void visitAronVariantOnEnter(const data::ListPtr&) override { lists++; }
void visitAronVariant(const data::NDArrayPtr&) override { ndarrays++; }
void visitAronVariant(const data::IntPtr&) override { ints++; }
void visitAronVariant(const data::LongPtr&) override { longs++; }
void visitAronVariant(const data::FloatPtr&) override { floats++; }
void visitAronVariant(const data::DoublePtr&) override { doubles++; }
void visitAronVariant(const data::BoolPtr&) override { strings++; }
void visitAronVariant(const data::StringPtr&) override { bools++; }
};
void countHowMany(const aron::data::VariantPtr& aron)
{
CountingRecursiveVisitor visitor;
std::cout << "The aron has " << visitor.dicts << " dicts." << std::endl;
}

Typed Visitors

Lessons Learned

armarx::FloatPtr
std::shared_ptr< float > FloatPtr
Definition: Transition.h:40
armarx::aron::component_config::getDictElements
std::map< std::string, std::pair< typename std::remove_const< DataInputT >::type, typename std::remove_const< TypeInputT >::type > > getDictElements(DataInputT &o, TypeInputT &t)
Definition: Util.h:73
armarx::aron::data::LongPtr
std::shared_ptr< Long > LongPtr
Definition: forward_declarations.h:26
armarx::aron::data::NDArrayPtr
std::shared_ptr< NDArray > NDArrayPtr
Definition: NDArray.h:46
armarx::aron::data::DoublePtr
std::shared_ptr< Double > DoublePtr
Definition: forward_declarations.h:32
armarx::VariantPtr
IceInternal::Handle< Variant > VariantPtr
Definition: Variant.h:42
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::aron::component_config::getListElements
std::vector< std::pair< typename std::remove_const< DataInputT >::type, typename std::remove_const< TypeInputT >::type > > getListElements(DataInputT &o, TypeInputT &t)
Definition: Util.h:97
VariantVisitor.h
armarx::aron::data::visitRecursive
requires isRecursiveVisitor< RecursiveVisitorImplementation, typename RecursiveVisitorImplementation::Input > void visitRecursive(RecursiveVisitorImplementation &v, typename RecursiveVisitorImplementation::Input &o)
Definition: RecursiveVisitor.h:146
armarx::aron::data::visit
requires isVisitor< VisitorImplementation, typename VisitorImplementation::Input > void visit(VisitorImplementation &v, typename VisitorImplementation::Input &o)
Definition: Visitor.h:124
armarx::aron::data::StringPtr
std::shared_ptr< String > StringPtr
Definition: forward_declarations.h:35
armarx::aron::data::IntPtr
std::shared_ptr< Int > IntPtr
Definition: forward_declarations.h:23
armarx::aron::type::Descriptor
Descriptor
Definition: Descriptor.h:76
armarx::aron::data::ListPtr
std::shared_ptr< List > ListPtr
Definition: List.h:40
armarx::aron::data::BoolPtr
std::shared_ptr< Bool > BoolPtr
Definition: forward_declarations.h:38