@@ -58,6 +58,84 @@ class PropertyMap;
5858// / initializer function, using given name from the passed property map
5959boost::any fromName (const PropertyMap& other, const std::string& other_name);
6060
61+ // hasSerialize<T>::value provides a true/false constexpr depending on whether operator<< is supported.
62+ // This uses SFINAE, extracted from https://jguegant.github.io/blogs/tech/sfinae-introduction.html
63+ template <typename T, typename = std::ostream&>
64+ struct hasSerialize : std::false_type
65+ {};
66+
67+ template <typename T>
68+ struct hasSerialize <T, decltype (std::declval<std::ostream&>() << std::declval<T>())> : std::true_type
69+ {};
70+
71+ template <typename T, typename = std::istream&>
72+ struct hasDeserialize : std::false_type
73+ {};
74+
75+ template <typename T>
76+ struct hasDeserialize <T, decltype (std::declval<std::istream&>() >> std::declval<T&>())> : std::true_type
77+ {};
78+
79+ class PropertySerializerBase
80+ {
81+ public:
82+ using SerializeFunction = std::string (*)(const boost::any&);
83+ using DeserializeFunction = boost::any (*)(const std::string&);
84+
85+ static std::string dummySerialize (const boost::any& /* unused*/ ) { return " " ; }
86+ static boost::any dummyDeserialize (const std::string& /* unused*/ ) { return boost::any (); }
87+
88+ protected:
89+ static bool insert (const std::type_index& type_index, const std::string& type_name, SerializeFunction serialize,
90+ DeserializeFunction deserialize);
91+ };
92+
93+ // / utility class to register serializer/deserializer functions for a property of type T
94+ template <typename T>
95+ class PropertySerializer : protected PropertySerializerBase
96+ {
97+ public:
98+ PropertySerializer () { insert (typeid (T), typeName<T>(), &serialize, &deserialize); }
99+
100+ template <class Q = T>
101+ static typename std::enable_if<ros::message_traits::IsMessage<Q>::value, std::string>::type typeName () {
102+ return ros::message_traits::DataType<T>::value ();
103+ }
104+
105+ template <class Q = T>
106+ static typename std::enable_if<!ros::message_traits::IsMessage<Q>::value, std::string>::type typeName () {
107+ return typeid (T).name ();
108+ }
109+
110+ private:
111+ /* * Serialization based on std::[io]stringstream */
112+ template <class Q = T>
113+ static typename std::enable_if<hasSerialize<Q>::value, std::string>::type serialize (const boost::any& value) {
114+ std::ostringstream oss;
115+ oss << boost::any_cast<T>(value);
116+ return oss.str ();
117+ }
118+ template <class Q = T>
119+ static typename std::enable_if<hasSerialize<Q>::value && hasDeserialize<Q>::value, boost::any>::type
120+ deserialize (const std::string& wired) {
121+ std::istringstream iss (wired);
122+ T value;
123+ iss >> value;
124+ return value;
125+ }
126+
127+ /* * No serialization available */
128+ template <class Q = T>
129+ static typename std::enable_if<!hasSerialize<Q>::value, std::string>::type serialize (const boost::any& value) {
130+ return dummySerialize (value);
131+ }
132+ template <class Q = T>
133+ static typename std::enable_if<!hasSerialize<Q>::value || !hasDeserialize<Q>::value, boost::any>::type
134+ deserialize (const std::string& wire) {
135+ return dummyDeserialize (wire);
136+ }
137+ };
138+
61139/* * Property is a wrapper for a boost::any value, also providing a default value and a description.
62140 *
63141 * Properties can be configured to be initialized from another PropertyMap - if still undefined.
@@ -122,6 +200,16 @@ class Property
122200 // / function callback used to initialize property value from another PropertyMap
123201 using InitializerFunction = std::function<boost::any(const PropertyMap&)>;
124202
203+ template <typename T>
204+ static Property fromMsg (const moveit_task_constructor_msgs::Property& msg) {
205+ auto requested_type{ typeid (T).name () };
206+ if (msg.type != requested_type) {
207+ throw type_error{ requested_type, msg.type };
208+ }
209+ PropertySerializer<T>(); // register serializer/deserializer
210+ return Property (typeid (T), msg.description , msg.value );
211+ };
212+
125213 // / set current value and default value
126214 void setValue (const boost::any& value);
127215 void setCurrentValue (const boost::any& value);
@@ -185,84 +273,6 @@ class Property
185273 InitializerFunction initializer_;
186274};
187275
188- // hasSerialize<T>::value provides a true/false constexpr depending on whether operator<< is supported.
189- // This uses SFINAE, extracted from https://jguegant.github.io/blogs/tech/sfinae-introduction.html
190- template <typename T, typename = std::ostream&>
191- struct hasSerialize : std::false_type
192- {};
193-
194- template <typename T>
195- struct hasSerialize <T, decltype (std::declval<std::ostream&>() << std::declval<T>())> : std::true_type
196- {};
197-
198- template <typename T, typename = std::istream&>
199- struct hasDeserialize : std::false_type
200- {};
201-
202- template <typename T>
203- struct hasDeserialize <T, decltype (std::declval<std::istream&>() >> std::declval<T&>())> : std::true_type
204- {};
205-
206- class PropertySerializerBase
207- {
208- public:
209- using SerializeFunction = std::string (*)(const boost::any&);
210- using DeserializeFunction = boost::any (*)(const std::string&);
211-
212- static std::string dummySerialize (const boost::any& /* unused*/ ) { return " " ; }
213- static boost::any dummyDeserialize (const std::string& /* unused*/ ) { return boost::any (); }
214-
215- protected:
216- static bool insert (const std::type_index& type_index, const std::string& type_name, SerializeFunction serialize,
217- DeserializeFunction deserialize);
218- };
219-
220- // / utility class to register serializer/deserializer functions for a property of type T
221- template <typename T>
222- class PropertySerializer : protected PropertySerializerBase
223- {
224- public:
225- PropertySerializer () { insert (typeid (T), typeName<T>(), &serialize, &deserialize); }
226-
227- template <class Q = T>
228- static typename std::enable_if<ros::message_traits::IsMessage<Q>::value, std::string>::type typeName () {
229- return ros::message_traits::DataType<T>::value ();
230- }
231-
232- template <class Q = T>
233- static typename std::enable_if<!ros::message_traits::IsMessage<Q>::value, std::string>::type typeName () {
234- return typeid (T).name ();
235- }
236-
237- private:
238- /* * Serialization based on std::[io]stringstream */
239- template <class Q = T>
240- static typename std::enable_if<hasSerialize<Q>::value, std::string>::type serialize (const boost::any& value) {
241- std::ostringstream oss;
242- oss << boost::any_cast<T>(value);
243- return oss.str ();
244- }
245- template <class Q = T>
246- static typename std::enable_if<hasSerialize<Q>::value && hasDeserialize<Q>::value, boost::any>::type
247- deserialize (const std::string& wired) {
248- std::istringstream iss (wired);
249- T value;
250- iss >> value;
251- return value;
252- }
253-
254- /* * No serialization available */
255- template <class Q = T>
256- static typename std::enable_if<!hasSerialize<Q>::value, std::string>::type serialize (const boost::any& value) {
257- return dummySerialize (value);
258- }
259- template <class Q = T>
260- static typename std::enable_if<!hasSerialize<Q>::value || !hasDeserialize<Q>::value, boost::any>::type
261- deserialize (const std::string& wire) {
262- return dummyDeserialize (wire);
263- }
264- };
265-
266276/* * PropertyMap is map of (name, Property) pairs.
267277 *
268278 * Conveniency methods are provided to setup property initialization for several
@@ -303,7 +313,8 @@ class PropertyMap
303313 Property& property (const std::string& name);
304314 const Property& property (const std::string& name) const { return const_cast <PropertyMap*>(this )->property (name); }
305315
306- void fillMsgs (std::vector<moveit_task_constructor_msgs::Property>& msg) const ;
316+ void fillMsgs (std::vector<moveit_task_constructor_msgs::Property>& msgs) const ;
317+ void fromMsgs (std::vector<moveit_task_constructor_msgs::Property>& msgs);
307318
308319 using iterator = std::map<std::string, Property>::iterator;
309320 using const_iterator = std::map<std::string, Property>::const_iterator;
0 commit comments