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_DETAIL_PROXYASPECT_HPP_
34 #define DART_COMMON_DETAIL_PROXYASPECT_HPP_
35 
36 #include "dart/common/Aspect.hpp"
37 
38 namespace dart {
39 namespace common {
40 namespace detail {
41 
42 //==============================================================================
43 template <class BaseT, class CompositeT, typename StateT>
44 class ProxyStateAspect : public BaseT
45 {
46 public:
47   using Base = BaseT;
48   using CompositeType = CompositeT;
49   using State = StateT;
50 
51   virtual ~ProxyStateAspect() = default;
52 
53   /// General constructor
54   template <typename... Args>
ProxyStateAspect(Args &&...args)55   ProxyStateAspect(Args&&... args)
56     : Base(std::forward<Args>(args)...), mProxyState()
57   {
58     // Do nothing
59   }
60 
61   // Documentation inherited
setAspectState(const Aspect::State & state)62   void setAspectState(const Aspect::State& state) override final
63   {
64     mProxyState.set(static_cast<const State&>(state));
65   }
66 
67   // Documentation inherited
getAspectState() const68   const Aspect::State* getAspectState() const override final
69   {
70     return &mProxyState;
71   }
72 
73   // Documentation inherited
cloneAspect() const74   std::unique_ptr<Aspect> cloneAspect() const override
75   {
76     return std::make_unique<ProxyStateAspect>();
77   }
78 
79 protected:
80   /// Reconfigure the Aspect to link it to this Aspect's new Composite
setComposite(Composite * newComposite)81   void setComposite(Composite* newComposite) override
82   {
83     Base::setComposite(newComposite);
84 
85     // Check if the Composite is the correct Owner type
86     typename State::Owner* owner
87         = dynamic_cast<typename State::Owner*>(newComposite);
88 
89     if (owner && mProxyState.getOwner() != owner)
90     {
91       // Link the ProxyState to its new owner
92       mProxyState = State(owner, mProxyState.get());
93     }
94   }
95 
96   /// Reconfigure the Aspect to unlink it from this Aspect's old Composite
loseComposite(Composite * oldComposite)97   void loseComposite(Composite* oldComposite) override
98   {
99     mProxyState = State(mProxyState.get());
100     Base::loseComposite(oldComposite);
101   }
102 
103   /// Proxy state for this Aspect
104   State mProxyState;
105 };
106 
107 //==============================================================================
108 template <class BaseT, class CompositeT, typename PropertiesT>
109 class ProxyPropertiesAspect : public BaseT
110 {
111 public:
112   using Base = BaseT;
113   using CompositeType = CompositeT;
114   using Properties = PropertiesT;
115 
116   virtual ~ProxyPropertiesAspect() = default;
117 
118   /// General constructor
119   template <typename... Args>
ProxyPropertiesAspect(Args &&...args)120   ProxyPropertiesAspect(Args&&... args)
121     : Base(std::forward<Args>(args)...), mProxyProperties()
122   {
123     // Do nothing
124   }
125 
126   // Documentation inherited
setAspectProperties(const Aspect::Properties & properties)127   void setAspectProperties(const Aspect::Properties& properties) override final
128   {
129     mProxyProperties.set(static_cast<const Properties&>(properties));
130   }
131 
132   // Documentation inherited
getAspectProperties() const133   const Aspect::Properties* getAspectProperties() const override final
134   {
135     return &mProxyProperties;
136   }
137 
138   // Documentation inherited
cloneAspect() const139   std::unique_ptr<Aspect> cloneAspect() const override
140   {
141     return std::make_unique<ProxyPropertiesAspect>();
142   }
143 
144 protected:
145   /// Reconfigure the Aspect to link it to this Aspect's new Composite
setComposite(Composite * newComposite)146   void setComposite(Composite* newComposite) override
147   {
148     Base::setComposite(newComposite);
149     typename Properties::Owner* owner
150         = dynamic_cast<typename Properties::Owner*>(newComposite);
151 
152     if (owner && mProxyProperties.getOwner() != owner)
153     {
154       // Link the ProxyProperties to its new owner
155       mProxyProperties = Properties(owner, mProxyProperties.get());
156     }
157   }
158 
159   /// Reconfigure the Aspect to unlink it from this Aspect's old Composite
loseComposite(Composite * oldComposite)160   void loseComposite(Composite* oldComposite) override
161   {
162     mProxyProperties = Properties(mProxyProperties.get());
163     Base::loseComposite(oldComposite);
164   }
165 
166   /// Proxy properties for this Aspect
167   Properties mProxyProperties;
168 };
169 
170 } // namespace detail
171 } // namespace common
172 } // namespace dart
173 
174 #endif // DART_COMMON_DETAIL_PROXYASPECT_HPP_
175