aron_conversions.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <map>
4 #include <memory>
5 #include <optional>
6 #include <type_traits>
7 #include <vector>
8 #include <algorithm>
9 
10 #include "Path.h"
11 
12 namespace armarx::aron
13 {
14 
15 namespace detail
16 {
17 
18  // Helper concept to avoid ambiguities
19  template<typename DtoT, typename BoT>
21 
22  template <class ...>
23  struct is_optional : public std::false_type {};
24 
25  template <class ...Ts>
26  struct is_optional<std::optional<Ts...>> : public std::true_type {};
27 
28 }
29 
30  /**
31  * Framework for converting ARON DTOs (Data Transfer Objects) to C++ BOs
32  * (Business Objects) and back.
33  *
34  * To allow conversion between custom ARON and C++ types, declare two
35  * functions in the namespace of the BO:
36  *
37  * @code
38  * // aron_conversions.h
39  *
40  * namespace bo_namespace
41  * {
42  * void toAron(arondto::MyObject& dto, const MyObject& bo);
43  * void fromAron(const arondto::MyObject& dto, MyObject& bo);
44  * }
45  * @endcode
46  *
47  * Note that the DTO always comes first, and the target object is
48  * non-const.
49  *
50  * In the implementation,
51  *
52  *
53  * @code
54  * // aron_conversions.cpp
55  *
56  * #include "aron_conversions.h"
57  * #include <Path/to/MyValue/aron_conversions.h>
58  *
59  * void bo_namespace::toAron(arondto::MyObject& dto, const MyObject& bo)
60  * {
61  * dto.name = bo.name;
62  * toAron(dto.myValue, bo.myValue);
63  * }
64  *
65  * void bo_namespace::fromAron(const arondto::MyObject& dto, MyObject& bo)
66  * {
67  * bo.name = dto.name;
68  * fromAron(dto.myValue, bo.myValue);
69  * }
70  * @endcode
71  */
72  // Same type
73  template <class T>
74  void toAron(T& dto, const T& bo)
75  {
76  dto = bo;
77  }
78  template <class T>
79  void fromAron(const T& dto, T& bo)
80  {
81  bo = dto;
82  }
83 
84 
85  // Generic return version
86  template <class DtoT, class BoT>
87  DtoT toAron(const BoT& bo)
88  {
89  DtoT dto;
90  toAron(dto, bo);
91  return dto;
92  }
93  template <class BoT, class DtoT>
94  BoT fromAron(const DtoT& dto)
95  {
96  BoT bo;
97  fromAron(dto, bo);
98  return bo;
99  }
100 
101 
102 
103 
104 
105 
106 
107  // std::unique_ptr
108  template <class DtoT, class BoT>
109  void toAron(DtoT& dto, const std::unique_ptr<BoT>& bo)
110  {
111  if (bo)
112  {
113  toAron(dto, *bo);
114  }
115  }
116 
117  template <class DtoT, class BoT>
118  void fromAron(const DtoT& dto, std::unique_ptr<BoT>& bo)
119  {
120  bo = std::make_unique<BoT>();
121  fromAron(dto, *bo);
122  }
123 
124 
125  // std::optional
126  template <class DtoT, class BoT>
127  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
128  void toAron(std::optional<DtoT>& dto, const std::optional<BoT>& bo)
129  {
130  if (bo.has_value())
131  {
132  dto = DtoT{};
133  toAron(*dto, *bo);
134  }
135  else
136  {
137  dto = std::nullopt;
138  }
139  }
140 
141  template <class DtoT, class BoT>
142  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
143  void fromAron(const std::optional<DtoT>& dto, std::optional<BoT>& bo)
144  {
145  if (dto.has_value())
146  {
147  bo = BoT{};
148  fromAron(*dto, *bo);
149  }
150  else
151  {
152  bo = std::nullopt;
153  }
154  }
155 
156 
157  // One-sided optional
158  template <class DtoT, class BoT>
160  void toAron(std::optional<DtoT>& dto, const BoT& bo)
161  {
162  dto = DtoT{};
163  toAron(*dto, bo);
164  }
165  template <class DtoT, class BoT>
167  void fromAron(DtoT& dto, const std::optional<BoT>& bo)
168  {
169  bo = BoT{};
170  fromAron(dto, *bo);
171  }
172 
173 
174  // Flag-controlled optional
175  template <class DtoT, class BoT>
176  void toAron(DtoT& dto, bool& dtoValid, const BoT& bo, bool boValid)
177  {
178  dtoValid = boValid;
179  if (boValid)
180  {
181  toAron(dto, bo);
182  }
183  else
184  {
185  dto = {};
186  }
187  }
188 
189 
190  template <class DtoT, class BoT>
191  void fromAron(const DtoT& dto, bool dtoValid, BoT& bo, bool& boValid)
192  {
193  boValid = dtoValid;
194  if (dtoValid)
195  {
196  fromAron(dto, bo);
197  }
198  else
199  {
200  bo = {};
201  }
202  }
203 
204  template <class DtoT, class BoT>
205  void toAron(DtoT& dto, bool& dtoValid, const std::optional<BoT>& bo)
206  {
207  dtoValid = bo.has_value();
208  if (dtoValid)
209  {
210  toAron(dto, *bo);
211  }
212  else
213  {
214  dto = {};
215  }
216  }
217 
218  template <class DtoT, class BoT>
219  void fromAron(const DtoT& dto, bool dtoValid, std::optional<BoT>& bo)
220  {
221  if (dtoValid)
222  {
223  bo = BoT{};
224  fromAron(dto, *bo);
225  }
226  else
227  {
228  bo = std::nullopt;
229  }
230  }
231 
232 
233  // std::vector
234  template <class DtoT, class BoT>
235  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
236  void toAron(std::vector<DtoT>& dtos, const std::vector<BoT>& bos)
237  {
238  dtos.clear();
239  dtos.reserve(bos.size());
240  for (const auto& bo : bos)
241  {
242  toAron(dtos.emplace_back(), bo);
243  }
244  }
245  template <class DtoT, class BoT>
246  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
247  void fromAron(const std::vector<DtoT>& dtos, std::vector<BoT>& bos)
248  {
249  bos.clear();
250  bos.reserve(dtos.size());
251  for (const auto& dto : dtos)
252  {
253  fromAron(dto, bos.emplace_back());
254  }
255  }
256 
257 
258  // std::map
259  template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT>
260  requires (!(detail::DtoAndBoAreSame<DtoKeyT, BoKeyT> and detail::DtoAndBoAreSame<DtoValueT, BoValueT>))
261  void toAron(std::map<DtoKeyT, DtoValueT>& dtoMap,
262  const std::map<BoKeyT, BoValueT>& boMap)
263  {
264  dtoMap.clear();
265  for (const auto& [boKey, boValue] : boMap)
266  {
267  DtoKeyT dtoKey;
268  toAron(dtoKey, boKey);
269  auto [it, _] = dtoMap.emplace(std::move(dtoKey), DtoValueT{});
270  toAron(it->second, boValue);
271  }
272  }
273  template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT>
274  requires (!(detail::DtoAndBoAreSame<DtoKeyT, BoKeyT> and detail::DtoAndBoAreSame<DtoValueT, BoValueT>))
275  void fromAron(const std::map<DtoKeyT, DtoValueT>& dtoMap,
276  std::map<BoKeyT, BoValueT>& boMap)
277  {
278  boMap.clear();
279  for (const auto& [dtoKey, dtoValue] : dtoMap)
280  {
281  BoKeyT boKey;
282  fromAron(dtoKey, boKey);
283  auto [it, _] = boMap.emplace(boKey, BoValueT{});
284  fromAron(dtoValue, it->second);
285  }
286  }
287 
288 
289  template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT>
290  requires (!(detail::DtoAndBoAreSame<DtoKeyT, BoKeyT> and detail::DtoAndBoAreSame<DtoValueT, BoValueT>))
291  std::map<DtoKeyT, DtoValueT> toAron(const std::map<BoKeyT, BoValueT>& boMap)
292  {
293  std::map<DtoKeyT, DtoValueT> dtoMap;
294  toAron(dtoMap, boMap);
295  return dtoMap;
296  }
297 }
298 
299 
300 
301 
302 
303 // And do the same for the armarx namespace to ensure consistency with all the other aron_conversions declaraions
304 // (which are usually in the armarx namespace)
305 namespace armarx
306 {
307  // Same type
308  template <class T>
309  void toAron(T& dto, const T& bo)
310  {
311  armarx::aron::toAron(dto, bo);
312  }
313  template <class T>
314  void fromAron(const T& dto, T& bo)
315  {
317  }
318 
319 
320  // Generic return version
321  template <class DtoT, class BoT>
322  DtoT toAron(const BoT& bo)
323  {
324  return armarx::aron::toAron<DtoT, BoT>(bo);
325  }
326  template <class BoT, class DtoT>
327  BoT fromAron(const DtoT& dto)
328  {
329  return armarx::aron::fromAron<BoT, DtoT>(dto);
330  }
331 
332  // std::unique_ptr
333  template <class DtoT, class BoT>
334  void toAron(DtoT& dto, const std::unique_ptr<BoT>& bo)
335  {
336  armarx::aron::toAron(dto, bo);
337  }
338  template <class DtoT, class BoT>
339  void fromAron(const DtoT& dto, std::unique_ptr<BoT>& bo)
340  {
342  }
343 
344  // std::optional
345  template <class DtoT, class BoT>
346  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
347  void toAron(std::optional<DtoT>& dto, const std::optional<BoT>& bo)
348  {
349  armarx::aron::toAron(dto, bo);
350  }
351  template <class DtoT, class BoT>
352  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
353  void fromAron(const std::optional<DtoT>& dto, std::optional<BoT>& bo)
354  {
356  }
357 
358  // Flag-controlled optional
359  template <class DtoT, class BoT>
360  void toAron(DtoT& dto, bool& dtoValid, const BoT& bo, bool boValid)
361  {
362  armarx::aron::toAron(dto, dtoValid, bo, boValid);
363  }
364  template <class DtoT, class BoT>
365  void fromAron(const DtoT& dto, bool dtoValid, BoT& bo, bool& boValid)
366  {
367  armarx::aron::fromAron(dto, dtoValid, bo, boValid);
368  }
369 
370  template <class DtoT, class BoT>
371  void toAron(DtoT& dto, bool& dtoValid, const std::optional<BoT>& bo)
372  {
373  armarx::aron::toAron(dto, dtoValid, bo);
374  }
375  template <class DtoT, class BoT>
376  void fromAron(const DtoT& dto, bool dtoValid, std::optional<BoT>& bo)
377  {
378  armarx::aron::fromAron(dto, dtoValid, bo);
379  }
380 
381  // std::vector
382  template <class DtoT, class BoT>
383  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
384  void toAron(std::vector<DtoT>& dtos, const std::vector<BoT>& bos)
385  {
386  armarx::aron::toAron(dtos, bos);
387  }
388  template <class DtoT, class BoT>
389  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
390  void fromAron(const std::vector<DtoT>& dtos, std::vector<BoT>& bos)
391  {
392  armarx::aron::fromAron(dtos, bos);
393  }
394 
395  template <class DtoT, class BoT>
396  requires (!aron::detail::DtoAndBoAreSame<DtoT, BoT>)
397  std::vector<DtoT> toAron(const std::vector<BoT>& bos)
398  {
399  return armarx::aron::toAron<DtoT, BoT>(bos);
400  }
401 
402 
403  // std::map
404  template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT>
405  requires (!(aron::detail::DtoAndBoAreSame<DtoKeyT, BoKeyT> and aron::detail::DtoAndBoAreSame<DtoValueT, BoValueT>))
406  void toAron(std::map<DtoKeyT, DtoValueT>& dtoMap, const std::map<BoKeyT, BoValueT>& boMap)
407  {
408  armarx::aron::toAron(dtoMap, boMap);
409  }
410  template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT>
411  requires (!(aron::detail::DtoAndBoAreSame<DtoKeyT, BoKeyT> and aron::detail::DtoAndBoAreSame<DtoValueT, BoValueT>))
412  void fromAron(const std::map<DtoKeyT, DtoValueT>& dtoMap, std::map<BoKeyT, BoValueT>& boMap)
413  {
414  armarx::aron::fromAron(dtoMap, boMap);
415  }
416 
417 
418  template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT>
419  requires (!(aron::detail::DtoAndBoAreSame<DtoKeyT, BoKeyT> and aron::detail::DtoAndBoAreSame<DtoValueT, BoValueT>))
420  std::map<DtoKeyT, DtoValueT> toAron(const std::map<BoKeyT, BoValueT>& boMap)
421  {
422  armarx::aron::toAron<DtoKeyT, DtoValueT, BoKeyT, BoValueT>(boMap);
423  }
424 
425  /**
426  * @brief Converter function for vector of aron elements to plain cpp type
427  *
428  * You have to provide a converter function for the element with the signature
429  *
430  * PlainCppType fromAron(const AronType&)
431  *
432  * @tparam T the aron vector element
433  * @param v the vector of elements
434  * @return the vector of aron elements
435  */
436  template <typename T>
437  auto fromAron(const std::vector<T>& v) -> std::vector<decltype(fromAron(T()))>
438  {
439  std::vector<decltype(fromAron(T()))> r;
440  r.reserve(v.size());
441 
442  std::transform(v.begin(), v.end(), std::back_inserter(r),
443  [](const T & t)
444  {
445  return fromAron(t);
446  });
447 
448  return r;
449  }
450 
451 
452  template <typename T> auto toAron(const std::vector<T>& v)
453  {
454  std::vector<decltype(toAron(T()))> r;
455  r.reserve(v.size());
456 
457  std::transform(v.begin(), v.end(), std::back_inserter(r),
458  [](const T & t)
459  {
460  return toAron(t);
461  });
462 
463  return r;
464  }
465 }
Path.h
armarx::requires
requires(!aron::detail::DtoAndBoAreSame< DtoT, BoT >) void toAron(std
Definition: aron_conversions.h:346
detail
Definition: OpenCVUtil.cpp:127
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::aron::detail::is_optional
Definition: aron_conversions.h:23
armarx::aron
Definition: DataDisplayVisitor.cpp:5
armarx::aron::requires
requires(!aron::detail::DtoAndBoAreSame< DtoT, BoT >) void toAron(std
Definition: aron_conversions.h:127
armarx::aron::detail::DtoAndBoAreSame
concept DtoAndBoAreSame
Definition: aron_conversions.h:20
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::aron::toAron
void toAron(T &dto, const T &bo)
Framework for converting ARON DTOs (Data Transfer Objects) to C++ BOs (Business Objects) and back.
Definition: aron_conversions.h:74
std
Definition: Application.h:66
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:315
armarx::fromAron
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
armarx::toAron
void toAron(arondto::PackagePath &dto, const PackageFileLocation &bo)
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
armarx::aron::fromAron
void fromAron(const T &dto, T &bo)
Definition: aron_conversions.h:79
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:168