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