1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  *   https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  *   Redistribution and use in source and binary forms, with or
10  *   without modification, are permitted provided that the following
11  *   conditions are met:
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above
15  *     copyright notice, this list of conditions and the following
16  *     disclaimer in the documentation and/or other materials provided
17  *     with the distribution.
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *   POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef DART_COMMON_EMBEDDEDASPECT_HPP_
34 #define DART_COMMON_EMBEDDEDASPECT_HPP_
35 
36 #include "dart/common/CompositeJoiner.hpp"
37 #include "dart/common/RequiresAspect.hpp"
38 #include "dart/common/detail/EmbeddedAspect.hpp"
39 
40 namespace dart {
41 namespace common {
42 
43 //==============================================================================
44 /// This is the implementation of a standard embedded-state Aspect. Inherit
45 /// the EmbedState class (next class down in the header) to use this Aspect
46 /// implementation.
47 ///
48 /// For more control over how your embedded-state Aspect is implemented, you can
49 /// use the detail::EmbeddedStateAspect class.
50 template <class CompositeT, typename StateDataT>
51 class EmbeddedStateAspect : public detail::EmbeddedStateAspect<
52                                 CompositeTrackingAspect<CompositeT>,
53                                 EmbeddedStateAspect<CompositeT, StateDataT>,
54                                 StateDataT>
55 {
56 public:
57   using Base = CompositeTrackingAspect<CompositeT>;
58   using Derived = EmbeddedStateAspect<CompositeT, StateDataT>;
59   using Impl = detail::EmbeddedStateAspect<Base, Derived, StateDataT>;
60   using State = typename Impl::State;
61   using StateData = typename Impl::StateData;
62 
63   template <typename... Args>
EmbeddedStateAspect(Args &&...args)64   EmbeddedStateAspect(Args&&... args) : Impl(std::forward<Args>(args)...)
65   {
66     // Do nothing
67   }
68 
69   virtual ~EmbeddedStateAspect() = default;
70 };
71 
72 //==============================================================================
73 /// Inherit this class to embed a State into your Composite object. DerivedT is
74 /// the name of your class and StateDataT is a "plain-old data" structure that
75 /// holds your state information.
76 ///
77 /// Your derived class must implement the following functions:
78 ///
79 /// \code{.cpp}
80 /// void setAspectState(const AspectState& state);
81 /// \endcode
82 ///
83 /// To embed both state and properties information, use EmbedStateAndProperties.
84 ///
85 /// It is possible to customize the way an EmbeddedStateAspect interacts with
86 /// your Composite by using the dart::common::detail::EmbeddedStateAspect class
87 /// directly instead of inheriting this class.
88 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN
89 
90 template <class DerivedT, typename StateDataT>
91 class EmbedState : public virtual common::RequiresAspect<
92                        common::EmbeddedStateAspect<DerivedT, StateDataT> >
93 {
94 public:
95   using Derived = DerivedT;
96   using Aspect = common::EmbeddedStateAspect<Derived, StateDataT>;
97   using AspectState = typename Aspect::State;
98   using AspectStateData = typename Aspect::StateData;
99   using Base = common::RequiresAspect<Aspect>;
100 
101   // Forwarding constructor
102   template <typename... Args>
EmbedState(Args &&...args)103   EmbedState(Args&&... args) : Base(std::forward<Args>(args)...)
104   {
105     // Do nothing
106   }
107 
108   virtual ~EmbedState() = default;
109 
getAspectState() const110   const AspectState& getAspectState() const
111   {
112     return mAspectState;
113   }
114 
115 protected:
116   /// Aspect::State data, directly accessible to your derived class
117   AspectState mAspectState;
118 };
119 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END
120 
121 //==============================================================================
122 /// This is an alternative to EmbedState which allows your class to also inherit
123 /// other Composite objects by listing them as the third (and later) template
124 /// arguments.
125 template <class DerivedT, typename StateDataT, typename... BaseComposites>
126 class EmbedStateOnTopOf
127   : public CompositeJoiner<EmbedState<DerivedT, StateDataT>, BaseComposites...>
128 {
129 public:
130   using Impl = EmbedState<DerivedT, StateDataT>;
131   using Derived = typename Impl::Derived;
132   using AspectStateData = typename Impl::AspectStateData;
133   using AspectState = typename Impl::AspectState;
134   using Aspect = typename Impl::Aspect;
135   using Base = CompositeJoiner<Impl, BaseComposites...>;
136   using Impl::getAspectState;
137 
138   // Forwarding constructor
139   template <typename... Args>
EmbedStateOnTopOf(Args &&...args)140   EmbedStateOnTopOf(Args&&... args) : Base(NoArg, std::forward<Args>(args)...)
141   {
142     // Do nothing
143   }
144 
145   virtual ~EmbedStateOnTopOf() = default;
146 
147 protected:
148   using Impl::mAspectState;
149 };
150 
151 //==============================================================================
152 /// This is the implementation of a standard embedded-properties Aspect. Inherit
153 /// the EmbedProperties (next class down in the header) to use this Aspect
154 /// implementation.
155 ///
156 /// For more control over how your embedded-properties Aspect is implemented,
157 /// you can use the detail::EmbeddedPropertiesAspect class.
158 template <class CompositeT, typename PropertiesDataT>
159 class EmbeddedPropertiesAspect
160   : public detail::EmbeddedPropertiesAspect<
161         CompositeTrackingAspect<CompositeT>,
162         EmbeddedPropertiesAspect<CompositeT, PropertiesDataT>,
163         PropertiesDataT>
164 {
165 public:
166   using Base = CompositeTrackingAspect<CompositeT>;
167   using Derived = EmbeddedPropertiesAspect<CompositeT, PropertiesDataT>;
168   using Impl = detail::EmbeddedPropertiesAspect<Base, Derived, PropertiesDataT>;
169   using Properties = typename Impl::Properties;
170   using PropertiesData = typename Impl::PropertiesData;
171 
172   // Forwarding constructor
173   template <typename... Args>
EmbeddedPropertiesAspect(Args &&...args)174   EmbeddedPropertiesAspect(Args&&... args) : Impl(std::forward<Args>(args)...)
175   {
176     // Do nothing
177   }
178 
179   virtual ~EmbeddedPropertiesAspect() = default;
180 };
181 
182 //==============================================================================
183 /// Inherit this class to embed Properties into your Composite object. DerivedT
184 /// is the name of your class and PropertiesDataT is a "plain-old data"
185 /// structure that holds your properties information.
186 ///
187 /// Your derived class must implement the following function:
188 ///
189 /// \code{.cpp}
190 /// void setAspectProperties(const AspectProperties& state);
191 /// \endcode
192 ///
193 /// To embed both state and properties information, use EmbedStateAndProperties.
194 ///
195 /// It is possible to customize the way an EmbeddedPropertiesAspect interacts
196 /// with your Composite by using the
197 /// dart::common::detail::EmbeddedPropertiesAspect class directly instead of
198 /// inheriting this class.
199 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN
200 template <class DerivedT, typename PropertiesDataT>
201 class EmbedProperties
202   : public virtual common::RequiresAspect<
203         common::EmbeddedPropertiesAspect<DerivedT, PropertiesDataT> >
204 {
205 public:
206   using Derived = DerivedT;
207   using Aspect = common::EmbeddedPropertiesAspect<Derived, PropertiesDataT>;
208   using AspectProperties = typename Aspect::Properties;
209   using AspectPropertiesData = typename Aspect::PropertiesData;
210   using Base = common::RequiresAspect<Aspect>;
211 
212   // Forwarding constructor
213   template <typename... Args>
EmbedProperties(Args &&...args)214   EmbedProperties(Args&&... args) : Base(std::forward<Args>(args)...)
215   {
216     // Do nothing
217   }
218 
219   virtual ~EmbedProperties() = default;
220 
getAspectProperties() const221   const AspectProperties& getAspectProperties() const
222   {
223     return mAspectProperties;
224   }
225 
226 protected:
227   /// Aspect::Properties data, directly accessible to your derived class
228   AspectProperties mAspectProperties;
229 };
230 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END
231 
232 //==============================================================================
233 /// This is an alternative to EmbedProperties which allows your class to also
234 /// inherit other Composite objects by listing them as the third (and later)
235 /// template arguments.
236 template <class DerivedT, typename PropertiesDataT, typename... CompositeBases>
237 class EmbedPropertiesOnTopOf : public CompositeJoiner<
238                                    EmbedProperties<DerivedT, PropertiesDataT>,
239                                    CompositeBases...>
240 {
241 public:
242   using Impl = EmbedProperties<DerivedT, PropertiesDataT>;
243   using Derived = typename Impl::Derived;
244   using AspectPropertiesData = typename Impl::AspectPropertiesData;
245   using AspectProperties = typename Impl::AspectProperties;
246   using Aspect = typename Impl::Aspect;
247   using Base = CompositeJoiner<Impl, CompositeBases...>;
248   using Impl::getAspectProperties;
249 
250   // Forwarding constructor
251   template <typename... Args>
EmbedPropertiesOnTopOf(Args &&...args)252   EmbedPropertiesOnTopOf(Args&&... args)
253     : Base(NoArg, std::forward<Args>(args)...)
254   {
255     // Do nothing
256   }
257 
258   virtual ~EmbedPropertiesOnTopOf() = default;
259 
260 protected:
261   using Impl::mAspectProperties;
262 };
263 
264 //==============================================================================
265 /// This is the implementation of a standard combination of embedded-state and
266 /// embedded-properties Aspect. Inherit the EmbedStateAndProperties (next class
267 /// down in the header) to use this Aspect implementation.
268 //
269 // Dev Note: We achieve "multiple inheritance" without the diamond of death
270 // issue by specifying detail::EmbeddedStateAspect as the base class of
271 // detail::EmbeddedPropertiesAspect. This allows their implementations to stack
272 // on top of each other without the conflict that would arise from both of them
273 // inheriting from common::Aspect.
274 template <class CompositeT, typename StateDataT, typename PropertiesDataT>
275 class EmbeddedStateAndPropertiesAspect
276   : public detail::EmbeddedPropertiesAspect<
277         detail::EmbeddedStateAspect<
278             CompositeTrackingAspect<CompositeT>,
279             EmbeddedStateAndPropertiesAspect<
280                 CompositeT,
281                 StateDataT,
282                 PropertiesDataT>,
283             StateDataT>,
284         EmbeddedStateAndPropertiesAspect<
285             CompositeT,
286             StateDataT,
287             PropertiesDataT>,
288         PropertiesDataT>
289 {
290 public:
291   using Derived = EmbeddedStateAndPropertiesAspect<
292       CompositeT,
293       StateDataT,
294       PropertiesDataT>;
295 
296   using AspectStateImpl = detail::EmbeddedStateAspect<
297       CompositeTrackingAspect<CompositeT>,
298       Derived,
299       StateDataT>;
300 
301   using AspectPropertiesImpl = detail::
302       EmbeddedPropertiesAspect<AspectStateImpl, Derived, PropertiesDataT>;
303 
304   using AspectImpl = Derived;
305 
306   using State = typename AspectStateImpl::State;
307   using StateData = typename AspectStateImpl::StateData;
308 
309   using Properties = typename AspectPropertiesImpl::Properties;
310   using PropertiesData = typename AspectPropertiesImpl::PropertiesData;
311 
312   using CompositeType = CompositeT;
313 
314   EmbeddedStateAndPropertiesAspect(const EmbeddedStateAndPropertiesAspect&)
315       = delete;
316 
317   virtual ~EmbeddedStateAndPropertiesAspect() = default;
318 
319   /// Construct using nothing. The object will remain unaffected.
EmbeddedStateAndPropertiesAspect()320   EmbeddedStateAndPropertiesAspect() : AspectPropertiesImpl()
321   {
322     // Do nothing
323   }
324 
325   /// Construct using a State. The object's Properties will remain unaffected.
EmbeddedStateAndPropertiesAspect(const StateData & state)326   EmbeddedStateAndPropertiesAspect(const StateData& state)
327     : AspectPropertiesImpl(state)
328   {
329     // Do nothing
330   }
331 
332   /// Construct using Properties. The object's State will remain unaffected.
EmbeddedStateAndPropertiesAspect(const PropertiesData & properties)333   EmbeddedStateAndPropertiesAspect(const PropertiesData& properties)
334     : AspectPropertiesImpl(properties)
335   {
336     // Do nothing
337   }
338 
339   /// Construct using a State and Properties instance
EmbeddedStateAndPropertiesAspect(const StateData & state,const PropertiesData & properties)340   EmbeddedStateAndPropertiesAspect(
341       const StateData& state, const PropertiesData& properties)
342     : AspectPropertiesImpl(properties, state)
343   {
344     // Do nothing
345   }
346 
347   /// Construct using a Properties and State instance
EmbeddedStateAndPropertiesAspect(const PropertiesData & properties,const StateData & state)348   EmbeddedStateAndPropertiesAspect(
349       const PropertiesData& properties, const StateData& state)
350     : AspectPropertiesImpl(properties, state)
351   {
352     // Do nothing
353   }
354 
355   // Documentation inherited
cloneAspect() const356   std::unique_ptr<Aspect> cloneAspect() const override
357   {
358     return std::make_unique<Derived>(this->getState(), this->getProperties());
359   }
360 };
361 
362 //==============================================================================
363 /// Inherit this class to embed both State and Properties into your Composite
364 /// object. DerivedT is the name of your class, StateDataT is a "plain-old data"
365 /// structure that holds your state information, and PropertiesDataT is a
366 /// "plain-old data" structure that holds your properties information.
367 ///
368 /// Your derived class must implement the following functions:
369 ///
370 /// \code{.cpp}
371 /// void setAspectState(const AspectState& state);
372 /// void setAspectProperties(const AspectProperties& state);
373 /// \endcode
374 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN
375 template <class DerivedT, typename StateDataT, typename PropertiesDataT>
376 class EmbedStateAndProperties : public virtual common::RequiresAspect<
377                                     common::EmbeddedStateAndPropertiesAspect<
378                                         DerivedT,
379                                         StateDataT,
380                                         PropertiesDataT> >
381 {
382 public:
383   using Derived = DerivedT;
384   using Aspect = common::
385       EmbeddedStateAndPropertiesAspect<DerivedT, StateDataT, PropertiesDataT>;
386 
387   using AspectState = typename Aspect::State;
388   using AspectStateData = typename Aspect::StateData;
389 
390   using AspectProperties = typename Aspect::Properties;
391   using AspectPropertiesData = typename Aspect::PropertiesData;
392   using Base = common::RequiresAspect<Aspect>;
393 
394   // Forwarding constructor
395   template <typename... Args>
EmbedStateAndProperties(Args &&...args)396   EmbedStateAndProperties(Args&&... args) : Base(std::forward<Args>(args)...)
397   {
398     // Do nothing
399   }
400 
401   virtual ~EmbedStateAndProperties() = default;
402 
getAspectState() const403   const AspectState& getAspectState() const
404   {
405     return mAspectState;
406   }
407 
getAspectProperties() const408   const AspectProperties& getAspectProperties() const
409   {
410     return mAspectProperties;
411   }
412 
413 protected:
414   /// Aspect::State data, directly accessible to your derived class
415   AspectState mAspectState;
416 
417   /// Aspect::Properties data, directly accessible to your derived class
418   AspectProperties mAspectProperties;
419 };
420 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END
421 
422 //==============================================================================
423 /// This is an alternative to EmbedStateAndProperties which allows your class to
424 /// also inherit other Composite objects by listing them as the fourth (and
425 /// later) template arguments.
426 template <
427     class DerivedT,
428     typename StateDataT,
429     typename PropertiesDataT,
430     typename... CompositeBases>
431 class EmbedStateAndPropertiesOnTopOf
432   : public CompositeJoiner<
433         EmbedStateAndProperties<DerivedT, StateDataT, PropertiesDataT>,
434         CompositeBases...>
435 {
436 public:
437   using Impl = EmbedStateAndProperties<DerivedT, StateDataT, PropertiesDataT>;
438   using Derived = typename Impl::Derived;
439   using AspectStateData = typename Impl::AspectStateData;
440   using AspectState = typename Impl::AspectState;
441   using AspectPropertiesData = typename Impl::AspectPropertiesData;
442   using AspectProperties = typename Impl::AspectProperties;
443   using Aspect = typename Impl::Aspect;
444   using Impl::getAspectProperties;
445   using Impl::getAspectState;
446   using Base = CompositeJoiner<Impl, CompositeBases...>;
447 
448   // Forwarding constructor
449   template <typename... Args>
EmbedStateAndPropertiesOnTopOf(Args &&...args)450   EmbedStateAndPropertiesOnTopOf(Args&&... args)
451     : Base(NoArg, std::forward<Args>(args)...)
452   {
453     // Do nothing
454   }
455 
456   virtual ~EmbedStateAndPropertiesOnTopOf() = default;
457 
458 protected:
459   using Impl::mAspectProperties;
460   using Impl::mAspectState;
461 };
462 
463 } // namespace common
464 } // namespace dart
465 
466 #endif // DART_COMMON_EMBEDDEDASPECT_HPP_
467