The objective of the utility is to simplify data translation from one object model to another. Examples of such translations are: BOM to API, ORM to BOM etc. There might be a need to support several versions of such translations like if one had several versions of API to support in parallel.
A model is given to the utility as a list of classes (type list). A single object of a class in the source model can be translated to a number of objects of different classes in the destination model.
The utility generates in compile time a special structure, which has inside an std::tuple<std::list<T1>, std::list<T2>, ...>
, where each std::list<Tx>
may hold a number of objects of the destination model. The model is defined as a boost::mpl::list<T1, T2, ...>
. In your translation method you call the provided add(tx)
function which appends to the appropriate list. After the translation is complete (= the structure is filled), you may visit all the generated objects in the order of types that you have specified in the model definition. The order matters in the case when you need to process (insert to a DB for example) parent objects before processing children which reference the parent. The reverse order would allow for processing (deleting from a DB for example) children before processing the parent.
The usage consists of these steps:
-
Define the destination model
ModelB
with the required order of classes:typedef a2b::model<ObjectB1, ObjectB2> ModelB;
or, which is the same:
typedef boost::mpl::list<ObjectB1, ObjectB2> ModelB;
-
Derive your translator
Translate2B
froma2b::Translator<Translate2B, ModelB>
, useadd
to fill the resulting structure:class Translate2B: public a2b::Translator<Translate2B, ModelB> { public: using base_type::translate; // to bring in some generic translations result_type translate(ObjectA1 const& obj) { return add( ObjectB1{ obj.x, obj.y } ); } };
The
add
function returns an intermediate result (a reference) whichtranslate
should return as well.The internal collection type, which by default is
std::list
, is configurable via thea2b::Translator
third template parameter, like this:class Translate2B: public a2b::Translator<Translate2B, ModelB, std::vector>;
The result of the translation in this case will have an
std::tuple
of differentstd::vector
types. -
Translate an object (or a collection of objects) by calling the
translate
method:std::vector<ObjectA1> const a1s = { ... }; ObjectA2 const a2; Translate2B tr; auto const& result = tr.translate(a2); // Here you call directly your translate method tr.translate(a1s); // Here you continue filling the same result object
-
Visit the objects with a visitor or manually by inspecting the result of the translation:
std::list<ObjectB1>& b1 = result.get<ObjectB1>(); class MyVisitor { public: void operator()(ObjectB1 const& b1) { print(b1); } void operator()(ObjectB2 const& b2) { print(b2); } }; result.visit(MyVisitor());
Use
reverse_visit
to visit in the reverse order.
cmake CMakeLists.txt
make
./runTests