OpenWalnut  1.5.0dev
WPropertyStruct.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WPROPERTYSTRUCT_H
26 #define WPROPERTYSTRUCT_H
27 
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/mpl/at.hpp>
33 #include <boost/mpl/copy.hpp>
34 #include <boost/mpl/size.hpp>
35 #include <boost/mpl/vector.hpp>
36 #include <boost/preprocessor/repetition/enum_params.hpp>
37 #include <boost/tuple/tuple.hpp>
38 
39 #include "WCondition.h"
40 #include "WPropertyBase.h"
41 #include "WPropertyGroupBase.h"
42 #include "WPropertyTypes.h"
43 #include "WStringUtils.h"
44 #include "exceptions/WPropertyUnknown.h"
45 
46 /**
47  * This contains some helping classes for compile time type conversion and similar.
48  */
50 {
51  /**
52  * Class to push a type from a sequence to the front of a tuple type
53  *
54  * \tparam T the sequence to convert.
55  * \tparam Tuple the tuple type, getting extended with the sequence types.
56  */
57  template< typename T, typename Tuple>
59 
60  /**
61  * Class to push a type from a sequence to the front of a tuple type. This is a specialization allowing to create a tuple from a list of
62  * types.
63  *
64  * \tparam T the sequence to convert.
65  * \tparam list of types to add to the tuple.
66  */
67  template< typename T, BOOST_PP_ENUM_PARAMS( 10, typename T )>
68  struct PushTypeToTupleFront< T, boost::tuple< BOOST_PP_ENUM_PARAMS( 10, T ) > >
69  {
70  /**
71  * The resulting tuple type
72  */
73  typedef boost::tuple< T, BOOST_PP_ENUM_PARAMS( 9, T ) > type;
74  };
75 
76  /**
77  * Converts a boost mpl sequence to a boost tuple
78  *
79  * \tparam Sequence the sequence to convert
80  */
81  template< typename Sequence >
83  {
84  /**
85  * This is the tuple type for the sequence
86  */
87  typedef typename boost::mpl::reverse_copy<
88  Sequence,
89  boost::mpl::inserter<
90  boost::tuple<>,
92  >
94  };
95 
96  /**
97  * Alias for default type to emulate variadic templates
98  */
99  typedef boost::mpl::na NOTYPE;
100 
101  /**
102  * Convert a list of template parameters to a boost::mpl::vector. This is currently done using the boost::mpl no-type type. This might get a
103  * problem some day?!
104  *
105  * \tparam T0 first type. Mandatory.
106  * \tparam T1 additional type. Optional.
107  * \tparam T2 additional type. Optional.
108  * \tparam T3 additional type. Optional.
109  * \tparam T4 additional type. Optional.
110  * \tparam T5 additional type. Optional.
111  * \tparam T6 additional type. Optional.
112  * \tparam T7 additional type. Optional.
113  * \tparam T8 additional type. Optional.
114  * \tparam T9 additional type. Optional.
115  */
116  template<
117  typename T0,
118  typename T1 = NOTYPE,
119  typename T2 = NOTYPE,
120  typename T3 = NOTYPE,
121  typename T4 = NOTYPE,
122  typename T5 = NOTYPE,
123  typename T6 = NOTYPE,
124  typename T7 = NOTYPE,
125  typename T8 = NOTYPE,
126  typename T9 = NOTYPE
127  >
128  struct AsVector
129  {
130  /**
131  * The template types as mpl vector
132  */
133  typedef boost::mpl::vector< BOOST_PP_ENUM_PARAMS( 10, T ) > type;
134  };
135 }
136 
137 /**
138  * Specialization which does nothing for the NOTYPE default template parameters of \ref WPropertyStruct.
139  */
140 template<>
142 {
143  /**
144  * The type of the initial value.
145  */
147 
148  /**
149  * Dummy method which does nothing for NOTYPE types.
150  */
151  static void createAndAdd( WPropertyGroupBase*, std::string, std::string, const ValueType& )
152  {
153  // NOTYPE will not cause any property creation.
154  }
155 
156  /**
157  * Dummy method which does nothing for NOTYPE types.
158  */
159  static void createAndAdd( WPropertyGroupBase*, std::string, std::string )
160  {
161  // NOTYPE will not cause any property creation.
162  }
163 };
164 
165 
166 /**
167  * This is a property which encapsulates a given, fixed number of other properties. You can specify up to 10 properties. This can be seen
168  * similar to the "struct" in the C++ language. A WPropertyStruct can basically seen as \ref WPropertyGroup, but is different in a certain way:
169  * it is fixed size (defined on compile time), it allows getting each property with their correct type and provides the appearance as if this
170  * property is only ONE object and not a group of multiple objects.
171  *
172  * \note the limitation to 10 types is due to the boost::tuple. If you need more, you need to replace the tuple type as storage-backend.
173  * \note if we use C++11 some day, we could use variadic templates here.
174  *
175  * \tparam T0 first type. Mandatory.
176  * \tparam T1 additional type. Optional.
177  * \tparam T2 additional type. Optional.
178  * \tparam T3 additional type. Optional.
179  * \tparam T4 additional type. Optional.
180  * \tparam T5 additional type. Optional.
181  * \tparam T6 additional type. Optional.
182  * \tparam T7 additional type. Optional.
183  * \tparam T8 additional type. Optional.
184  * \tparam T9 additional type. Optional.
185  */
186 template<
187  typename T0,
188  typename T1 = WPropertyStructHelper::NOTYPE,
189  typename T2 = WPropertyStructHelper::NOTYPE,
190  typename T3 = WPropertyStructHelper::NOTYPE,
191  typename T4 = WPropertyStructHelper::NOTYPE,
192  typename T5 = WPropertyStructHelper::NOTYPE,
193  typename T6 = WPropertyStructHelper::NOTYPE,
194  typename T7 = WPropertyStructHelper::NOTYPE,
195  typename T8 = WPropertyStructHelper::NOTYPE,
196  typename T9 = WPropertyStructHelper::NOTYPE
197 >
199 {
200 friend class WPropertyStructTest; //!< Access for test class.
201 public:
202  /**
203  * The type of this template instantiation.
204  */
205  typedef WPropertyStruct< BOOST_PP_ENUM_PARAMS( 10, T ) > WPropertyStructType;
206 
207  /**
208  * Convenience typedef for a std::shared_ptr< WPropertyStructType >
209  */
210  typedef typename std::shared_ptr< WPropertyStructType > SPtr;
211 
212  /**
213  * Convenience typedef for a std::shared_ptr< const WPropertyStructType >
214  */
215  typedef typename std::shared_ptr< const WPropertyStructType > ConstSPtr;
216 
217  /**
218  * The boost mpl vector for all the types specified.
219  */
220  typedef typename WPropertyStructHelper::AsVector< BOOST_PP_ENUM_PARAMS( 10, T ) >::type TypeVector;
221 
222  /**
223  * The type vector as a boost tuple.
224  */
226 
227  /**
228  * Create an empty named property.
229  *
230  * \param name the name of the property
231  * \param description the description of the property
232  */
233  WPropertyStruct( std::string name, std::string description ):
234  WPropertyGroupBase( name, description )
235  {
236  // now create the property instances
237  PropertyCreatorAndGroupAdder< T0 >::createAndAdd( this, name + "_Prop0", "No description for Property 0 in struct \"" + name + "\"." );
238  PropertyCreatorAndGroupAdder< T1 >::createAndAdd( this, name + "_Prop1", "No description for Property 1 in struct \"" + name + "\"." );
239  PropertyCreatorAndGroupAdder< T2 >::createAndAdd( this, name + "_Prop2", "No description for Property 2 in struct \"" + name + "\"." );
240  PropertyCreatorAndGroupAdder< T3 >::createAndAdd( this, name + "_Prop3", "No description for Property 3 in struct \"" + name + "\"." );
241  PropertyCreatorAndGroupAdder< T4 >::createAndAdd( this, name + "_Prop4", "No description for Property 4 in struct \"" + name + "\"." );
242  PropertyCreatorAndGroupAdder< T5 >::createAndAdd( this, name + "_Prop5", "No description for Property 5 in struct \"" + name + "\"." );
243  PropertyCreatorAndGroupAdder< T6 >::createAndAdd( this, name + "_Prop6", "No description for Property 6 in struct \"" + name + "\"." );
244  PropertyCreatorAndGroupAdder< T7 >::createAndAdd( this, name + "_Prop7", "No description for Property 7 in struct \"" + name + "\"." );
245  PropertyCreatorAndGroupAdder< T8 >::createAndAdd( this, name + "_Prop8", "No description for Property 8 in struct \"" + name + "\"." );
246  PropertyCreatorAndGroupAdder< T9 >::createAndAdd( this, name + "_Prop9", "No description for Property 9 in struct \"" + name + "\"." );
247  }
248 
249  /**
250  * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
251  * created. The subscriptions to a signal are LOST as well as all listeners to a condition.
252  *
253  * \param from the instance to copy.
254  */
255  explicit WPropertyStruct( const WPropertyStructType& from ):
256  WPropertyGroupBase( from )
257  {
258  // this created a NEW update condition and NEW property instances (clones)
259  }
260 
261  /**
262  * Destructor.
263  */
265  {
266  // the storing tuple is destroyed automatically and the properties if not used anymore
267  }
268 
269  /**
270  * Get the N'th property in the struct.
271  *
272  * \tparam N the number of the property to get.
273  *
274  * \return the property.
275  */
276  template< int N >
277  typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type getProperty()
278  {
279  typedef typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type TargetType;
280  return std::dynamic_pointer_cast< TargetType >( getProperty( N ) );
281  }
282 
283  /**
284  * Get the N'th property in the struct.
285  *
286  * \tparam N the number of the property to get.
287  *
288  * \return the property.
289  */
290  template< int N >
291  typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type::ConstSPtr getProperty() const
292  {
293  typedef typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type TargetType;
294  return std::dynamic_pointer_cast< const TargetType >( getProperty( N ) );
295  }
296 
297  /**
298  * Returns the property with the given number, but only as base type. The advantage is that the property number can be specified during
299  * runtime.
300  *
301  * \param n the number of the property
302  *
303  * \return the property
304  */
305  const WPropertyBase::SPtr& getProperty( size_t n ) const
306  {
307  // lock, unlocked if l looses focus
309  return l->get()[ n ];
310  }
311 
312  /**
313  * Returns the property with the given number, but only as base type. The advantage is that the property number can be specified during
314  * runtime.
315  *
316  * \param n the number of the property
317  *
318  * \return the property
319  */
321  {
322  // lock, unlocked if l looses focus
324  return l->get()[ n ];
325  }
326 
327  /**
328  * The size of the WPropertyStruct. This returns the number of properties encapsulated.
329  *
330  * \return number of properties in struct
331  */
332  size_t size() const
333  {
334  return m_size;
335  }
336 
337  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338  // The WPropertyBase specific stuff
339  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
340 
341  /**
342  * This method clones a property and returns the clone. It does a deep copy and, in contrast to a copy constructor, creates property with the
343  * correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls
344  * subscribed signal handlers are NOT copied.
345  *
346  * \note this simply ensures the copy constructor of the runtime type is issued.
347  *
348  * \return the deep clone of this property.
349  */
351  {
352  // just use the copy constructor
353  return typename WPropertyStructType::SPtr( new WPropertyStructType( *this ) );
354  }
355 
356  /**
357  * Gets the real WPropertyVariable type of this instance.
358  *
359  * \return the real type.
360  */
361  virtual PROPERTY_TYPE getType() const
362  {
363  return PV_STRUCT;
364  }
365 
366  /**
367  * This methods allows properties to be set by a string value. This is especially useful when a property is only available as string and the
368  * real type of the property is unknown. This is a shortcut for casting the property and then setting the lexically casted value.
369  *
370  * \param value the new value to set.
371  *
372  * \return true if value could be set.
373  */
374  virtual bool setAsString( std::string value )
375  {
376  // this method splits the given string and simply forwards the call to the other properties
377  std::vector< std::string > propsAsString = string_utils::tokenize( value, "|", false );
378  if( size() != propsAsString.size() )
379  {
380  return false;
381  }
382 
383  // lock, unlocked if l looses focus
385  // give the string to each property
386  size_t curPropNb = 0;
387  bool success = true;
388  for( std::vector< std::string >::const_iterator iter = propsAsString.begin(); iter != propsAsString.end(); ++iter )
389  {
390  success = success && l->get()[ curPropNb ]->setAsString( *iter );
391  curPropNb++;
392  }
393  return success;
394  }
395 
396  /**
397  * Returns the current value as a string. This is useful for debugging or project files. It is not implemented as << operator, since the <<
398  * should also print min/max constraints and so on. This simply is the value.
399  *
400  * \return the value as a string.
401  */
402  virtual std::string getAsString()
403  {
404  // lock, unlocked if l looses focus
406 
407  // go through and append each prop
408  std::string result = "";
409  for( size_t i = 0; i < size(); ++i )
410  {
411  result += l->get()[ i ]->getAsString() + "|";
412  }
413  // strip last "|"
414  result.erase( result.length() - 1, 1 );
415  return result;
416  }
417 
418  /**
419  * Sets the value from the specified property to this one. This is especially useful to copy a value without explicitly casting/knowing the
420  * dynamic type of the property.
421  *
422  * \param value the new value.
423  * \param recommendedOnly if true, property types which support recommended values apply the given value as recommendation.
424  *
425  * \return true if the value has been accepted.
426  */
427  virtual bool set( std::shared_ptr< WPropertyBase > value, bool recommendedOnly = false )
428  {
429  // is this the same type as we are?
430  typename WPropertyStructType::SPtr v = std::dynamic_pointer_cast< WPropertyStructType >( value );
431  if( !v )
432  {
433  // it is not a WPropertyStruct with the same type
434  return false;
435  }
436 
437  // lock, unlocked if l looses focus
439  PropertySharedContainerType::ReadTicket lother = v->m_properties.getReadTicket();
440  bool success = true;
441  // set each property
442  for( size_t curPropNb = 0; curPropNb < size(); ++curPropNb )
443  {
444  success = success && l->get()[ curPropNb ]->set( lother->get()[ curPropNb ], recommendedOnly );
445  }
446 
447  return success;
448  }
449 
450 protected:
451 private:
452  /**
453  * How many elements are in this WPropertyStruct?
454  */
455  static const size_t m_size = boost::mpl::size< TypeVector >::value;
456 };
457 
458 #endif // WPROPERTYSTRUCT_H
459 
std::shared_ptr< WPropertyBase > SPtr
Convenience typedef for a std::shared_ptr< WPropertyBase >
Definition: WPropertyBase.h:53
This is the base class and interface for property groups.
PropertySharedContainerType m_properties
The set of proerties.
Test WPropertyStruct.
This is a property which encapsulates a given, fixed number of other properties.
WPropertyStruct(std::string name, std::string description)
Create an empty named property.
WPropertyStruct< BOOST_PP_ENUM_PARAMS(10, T) > WPropertyStructType
The type of this template instantiation.
boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type::ConstSPtr getProperty() const
Get the N'th property in the struct.
virtual std::string getAsString()
Returns the current value as a string.
size_t size() const
The size of the WPropertyStruct.
std::shared_ptr< WPropertyStructType > SPtr
Convenience typedef for a std::shared_ptr< WPropertyStructType >
static const size_t m_size
How many elements are in this WPropertyStruct?
const WPropertyBase::SPtr & getProperty(size_t n) const
Returns the property with the given number, but only as base type.
std::shared_ptr< const WPropertyStructType > ConstSPtr
Convenience typedef for a std::shared_ptr< const WPropertyStructType >
virtual WPropertyBase::SPtr clone()
This method clones a property and returns the clone.
WPropertyStructHelper::AsVector< BOOST_PP_ENUM_PARAMS(10, T) >::type TypeVector
The boost mpl vector for all the types specified.
virtual PROPERTY_TYPE getType() const
Gets the real WPropertyVariable type of this instance.
virtual bool setAsString(std::string value)
This methods allows properties to be set by a string value.
boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type getProperty()
Get the N'th property in the struct.
virtual bool set(std::shared_ptr< WPropertyBase > value, bool recommendedOnly=false)
Sets the value from the specified property to this one.
WPropertyStructHelper::SequenceToTuple< TypeVector >::type TupleType
The type vector as a boost tuple.
WPropertyBase::SPtr getProperty(size_t n)
Returns the property with the given number, but only as base type.
WPropertyStruct(const WPropertyStructType &from)
Copy constructor.
virtual ~WPropertyStruct()
Destructor.
std::shared_ptr< WSharedObjectTicketRead< T > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
This contains some helping classes for compile time type conversion and similar.
boost::mpl::na NOTYPE
Alias for default type to emulate variadic templates.
std::vector< std::string > tokenize(const std::string &source, const std::string &delim=WHITESPACE, bool compress=true)
Splits the given string into a vector of strings (so called tokens).
WPropertyStructHelper::NOTYPE ValueType
The type of the initial value.
static void createAndAdd(WPropertyGroupBase *, std::string, std::string, const ValueType &)
Dummy method which does nothing for NOTYPE types.
static void createAndAdd(WPropertyGroupBase *, std::string, std::string)
Dummy method which does nothing for NOTYPE types.
Comfortable template to create a property instance and add it to the group.
static void createAndAdd(WPropertyGroupBase *group, std::string name, std::string description, const ValueType &initial=ValueType())
Actually does the work and adds a new property with the given name, description and other parameters ...
Convert a list of template parameters to a boost::mpl::vector.
boost::mpl::vector< BOOST_PP_ENUM_PARAMS(10, T) > type
The template types as mpl vector.
boost::tuple< T, BOOST_PP_ENUM_PARAMS(9, T) > type
The resulting tuple type.
Class to push a type from a sequence to the front of a tuple type.
Converts a boost mpl sequence to a boost tuple.
boost::mpl::reverse_copy< Sequence, boost::mpl::inserter< boost::tuple<>, PushTypeToTupleFront< boost::mpl::_2, boost::mpl::_1 > > >::type type
This is the tuple type for the sequence.