OpenWalnut  1.5.0dev
WPropertyVariable.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 WPROPERTYVARIABLE_H
26 #define WPROPERTYVARIABLE_H
27 
28 #include <list>
29 #include <memory>
30 #include <set>
31 #include <stdint.h>
32 #include <string>
33 
34 #include <boost/signals2.hpp>
35 
36 #include "WCondition.h"
37 #include "WFlag.h"
38 #include "WPropertyBase.h"
39 #include "WSharedAssociativeContainer.h"
40 #include "WSharedObjectTicketRead.h"
41 #include "WSharedObjectTicketWrite.h"
42 #include "constraints/WPropertyConstraintIsDirectory.h"
43 #include "constraints/WPropertyConstraintMax.h"
44 #include "constraints/WPropertyConstraintMin.h"
45 #include "constraints/WPropertyConstraintNotEmpty.h"
46 #include "constraints/WPropertyConstraintPathExists.h"
47 #include "constraints/WPropertyConstraintSelectOnlyOne.h"
48 #include "constraints/WPropertyConstraintTypes.h"
49 
50 /**
51  * A named property class with a concrete type.
52  */
53 template< typename T >
54 class WPropertyVariable: public WFlag< T >,
55  public WPropertyBase
56 {
57  friend class WPropertyVariableTest; //!< Access for test class.
58 public:
59  /**
60  * Convenience typedef for a shared_ptr of WPropertyVariable.
61  */
62  typedef std::shared_ptr< WPropertyVariable< T > > SPtr;
63 
64  /**
65  * Convenience typedef for a shared_ptr of const WPropertyVariable.
66  */
67  typedef std::shared_ptr< const WPropertyVariable< T > > ConstSPtr;
68 
69  //! The type of the data of this property.
70  typedef T DataType;
71 
72  /**
73  * Create an empty instance just containing a name.
74  *
75  * \param name the property name
76  * \param description the property description
77  * \param initial the initial value
78  */
79  WPropertyVariable( std::string name, std::string description, const T& initial );
80 
81  /**
82  * Create an empty instance just containing a name. This constructor allows an external condition to be used for notifiaction.
83  * This is practical if one would like to share a condition among several properties.
84  *
85  * \param name the property name
86  * \param description the property description
87  * \param initial the initial value
88  * \param condition use this external condition for notification.
89  */
90  WPropertyVariable( std::string name, std::string description, const T& initial, std::shared_ptr< WCondition > condition );
91 
92  /**
93  * Create an empty instance just containing a name. This constructor allows an external callback to be used for notification.
94  *
95  * \param name the property name
96  * \param description the property description
97  * \param initial the initial value
98  * \param notifier use this notifier for change callbacks.
99  *
100  * \note: instead of setting another notifier, you should consider using the callbacks the condition offers.
101  * \note: the notifiers gets connected to the notification callback of the internal condition. So be careful when using the
102  * condition ( getCondition() ) for other properties, since they would also share the callbacks
103  *
104  */
105  WPropertyVariable( std::string name, std::string description, const T& initial, PropertyChangeNotifierType notifier );
106 
107  /**
108  * Create an empty instance just containing a name. This constructor allows an external callback and condition to be used for notification.
109  *
110  * \param name the property name
111  * \param description the property description
112  * \param initial the initial value
113  * \param notifier use this notifier for change callbacks.
114  * \param condition use this external condition for notification
115  *
116  * \note: instead of setting another notifier, you should consider using the callbacks the condition offers.
117  * \note: the notifiers gets connected to the notification callback of the internal condition. So be careful when using the
118  * condition ( getCondition() ) for other properties, since they would also share the callbacks
119  *
120  */
121  WPropertyVariable( std::string name, std::string description, const T& initial, std::shared_ptr< WCondition > condition,
122  PropertyChangeNotifierType notifier );
123 
124  /**
125  * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
126  * created. The subscriptions to a signal are LOST as well as all listeners to a condition.
127  * The conditions you can grab using getValueChangeConditon and getCondition are not the same as in the original! This is because
128  * the class corresponds to the observer/observable pattern. You won't expect a clone to fire a condition if a original variable is changed
129  * (which after cloning is completely decoupled from the clone).
130  *
131  * \param from the instance to copy.
132  */
133  explicit WPropertyVariable( const WPropertyVariable< T >& from );
134 
135  /**
136  * Destructor.
137  */
138  virtual ~WPropertyVariable();
139 
140  /**
141  * 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
142  * correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls
143  * subscribed signal handlers are NOT copied.
144  *
145  * \note this simply ensures the copy constructor of the runtime type is issued.
146  *
147  * \return the deep clone of this property.
148  */
149  virtual std::shared_ptr< WPropertyBase > clone();
150 
151  /**
152  * Determines whether the specified value is acceptable.
153  *
154  * \param newValue the new value.
155  *
156  * \return true if it is a valid/acceptable value.
157  */
158  virtual bool accept( const T& newValue );
159 
160  /**
161  * This method is useful to ensure, that there is a valid value in the property. Assume the following situation. The property p got a min
162  * value of 10. p->setMin( 10 ). Now, p gets set by the GUI to 11. Now your module sets another min value: p->setMin( 15 ). As the property
163  * already has been set, the property can't decide what to do; it simply stays invalid. To ensure a valid value, you can use this method. It
164  * only sets the new value if the old value is invalid.
165  *
166  * \param newValidValue the new value to set.
167  * \param suppressNotification true to avoid a firing condition.
168  *
169  * \return true if the new value has been accepted ( if it was valid ) - for short true if the property NOW is valid
170  */
171  virtual bool ensureValidity( const T& newValidValue, bool suppressNotification = false );
172 
173  /**
174  * Class building the base for user defined constraints on a property instance.
175  */
177  {
178  public:
179  /**
180  * Default constructor.
181  */
183 
184  /**
185  * Destructor.
186  */
187  virtual ~PropertyConstraint();
188 
189  /**
190  * This method decides whether the specified value is valid for a specific property.
191  *
192  * \param value the new value.
193  * \param property the property to which the value should be set.
194  *
195  * \return true whenever the new value is acceptable for the property.
196  */
197  virtual bool accept( std::shared_ptr< WPropertyVariable< T > > property, const T& value ) = 0;
198 
199  /**
200  * Allows simple identification of the real constraint type.
201  *
202  * \return the type
203  */
204  virtual PROPERTYCONSTRAINT_TYPE getType();
205 
206  /**
207  * This method creates a constraint using the specified type. This is a useful convenience class for easily adding
208  * constraints.
209  *
210  * \param type the type of the constraint to create
211  *
212  * \return NULL if the type is unknown or an constraint instance
213  */
214  static std::shared_ptr< PropertyConstraint > create( PROPERTYCONSTRAINT_TYPE type );
215 
216  /**
217  * Method to clone the constraint and create a new one with the correct dynamic type.
218  *
219  * \return the constraint.
220  */
221  virtual std::shared_ptr< PropertyConstraint > clone() = 0;
222  };
223 
224  /**
225  * The alias for a shared container.
226  */
228 
229  /**
230  * Alias for min constraints. It is an alias for convenience.
231  */
232  typedef std::shared_ptr< WPropertyConstraintMin< T > > PropertyConstraintMin;
233 
234  /**
235  * Alias for max constraints. It is an alias for convenience.
236  */
237  typedef std::shared_ptr< WPropertyConstraintMax< T > > PropertyConstraintMax;
238 
239  /**
240  * Add a new constraint. This is useful to disallow several (custom) values for this property.
241  *
242  * \param constraint the new constraint.
243  *
244  */
245  void addConstraint( std::shared_ptr< PropertyConstraint > constraint );
246 
247  /**
248  * Returns all the current constraints of a WPropertyVariable. They can be iterated using the provided access object.
249  *
250  * \return the constraint access object
251  */
253 
254  /**
255  * Gets the condition, which gets notified whenever the list of constraints changes. It is notified AFTER the write lock has been released so
256  * a read lock can be acquired in the callback.
257  *
258  * \return the condition.
259  */
260  std::shared_ptr< WCondition > getContraintsChangedCondition();
261 
262  /**
263  * Creates a new WPropertyConstraintMin for this WPropertyVariable.
264  *
265  * \param min the minimum value.
266  *
267  * \return the new constraint.
268  */
269  static PropertyConstraintMin minConstraint( const T& min );
270 
271  /**
272  * Creates a new WPropertyConstraintMax for this WPropertyVariable.
273  *
274  * \param max the maximum value of the property
275  *
276  * \return the new constraint.
277  */
278  static PropertyConstraintMax maxConstraint( const T& max );
279 
280  /**
281  * Set a minimum constraint.
282  *
283  * \param min the minimum value allowed.
284  *
285  * \return the newly created constraint.
286  */
287  PropertyConstraintMin setMin( const T& min );
288 
289  /**
290  * Set a maximum constraint.
291  *
292  * \param max the maximum value allowed.
293  *
294  * \return the newly created constraint.
295  */
296  PropertyConstraintMax setMax( const T& max );
297 
298  /**
299  * Gets the current minimum constraint value.
300  *
301  * \return the minimum constraint, or NULL if none.
302  */
304 
305  /**
306  * Gets the current maximum constraint value.
307  *
308  * \return the maximum constraint, or NULL if none.
309  */
311 
312  /**
313  * This replaces all existing constraints of a certain type by a new specified constraint.
314  *
315  * \param constraint the new constraint
316  * \param type the type of constraints to replace
317  */
318  void replaceConstraint( std::shared_ptr< PropertyConstraint > constraint, PROPERTYCONSTRAINT_TYPE type );
319 
320  /**
321  * This replaces all existing constraints of a certain type by a new specified constraint.
322  *
323  * \param constraint the new constraint
324  * \param type the type of constraints to replace
325  * \return the constraint created
326  */
327  std::shared_ptr< PropertyConstraint > replaceConstraint( PROPERTYCONSTRAINT_TYPE constraint, PROPERTYCONSTRAINT_TYPE type );
328 
329  /**
330  * Cleans list of constraints from all existing constrains of the specified type.
331  *
332  * \param type the type to remove.
333  */
334  void removeConstraint( PROPERTYCONSTRAINT_TYPE type );
335 
336  /**
337  * Removes the specified constraint if existent.
338  *
339  * \param constraint the constraint to remove.
340  */
341  void removeConstraint( std::shared_ptr< PropertyConstraint > constraint );
342 
343  /**
344  * Method searching the first appearance of a constrained with the specified type.
345  *
346  * \param type the type of the searched constraint
347  *
348  * \return the constraint, or NULL if none.
349  */
350  std::shared_ptr< PropertyConstraint > getFirstConstraint( PROPERTYCONSTRAINT_TYPE type );
351 
352  /**
353  * Method searching the first appearance of a constrained with the specified type.
354  *
355  * \param type the type of the searched constraint
356  *
357  * \return the constraint, or NULL if none.
358  */
359  int countConstraint( PROPERTYCONSTRAINT_TYPE type );
360 
361  /**
362  * 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
363  * real type of the property is unknown. This is a shortcut for casting the property and then setting the lexically casted value.
364  *
365  * \param value the new value to set.
366  *
367  * \return true if value could be set.
368  */
369  virtual bool setAsString( std::string value );
370 
371  /**
372  * Returns the current value as a string. This is useful for debugging or project files. It is not implemented as << operator, since the <<
373  * should also print min/max constraints and so on. This simply is the value.
374  *
375  * \return the value as a string.
376  */
377  virtual std::string getAsString();
378 
379  /**
380  * Sets the value from the specified property to this one. This is especially useful to copy a value without explicitly casting/knowing the
381  * dynamic type of the property.
382  *
383  * \param value the new value.
384  * \param recommendedOnly if true, property types which support recommended values apply the given value as recommendation.
385  *
386  * \return true if the value has been accepted.
387  */
388  virtual bool set( std::shared_ptr< WPropertyBase > value, bool recommendedOnly = false );
389 
390  /**
391  * Sets the new value for this flag. Also notifies waiting threads. After setting a value, changed() will be true.
392  *
393  * \param value the new value
394  * \param suppressNotification true to avoid a firing condition. This is useful for resetting values.
395  *
396  * \return true if the value has been set successfully.
397  *
398  * \note set( get() ) == true
399  * \note this is defined here to help the compiler to disambiguate between WFlag::set and the WPropertyBase::set.
400  */
401  virtual bool set( const T& value, bool suppressNotification = false );
402 
403  /**
404  * Sets the specified value as recommended value. The difference to \ref set is simple. If some value was set using the method \ref set
405  * earlier, the \ref setRecommendedValue call is ignored. This is very useful in modules, where incoming data yields some useful default values
406  * but you do not want to overwrite a user-value which might have been set.
407  *
408  * \param value the new value to set if the user did not yet set the value
409  *
410  * \return true if value has been set successfully.
411  */
412  virtual bool setRecommendedValue( const T& value );
413 
414 protected:
415  /**
416  * The connection used for notification.
417  */
418  boost::signals2::connection m_notifierConnection;
419 
420  /**
421  * Uses typeid() to set the proper type constant.
422  */
423  virtual void updateType();
424 
425  /**
426  * Cleans list of constraints from all existing constrains of the specified type.
427  *
428  * \param type the type to remove.
429  * \param ticket the write ticket if already existent.
430  */
431  void removeConstraints( PROPERTYCONSTRAINT_TYPE type,
434 
435  /**
436  * This method gets called by WFlag whenever the value of the property changes. It re-emits the signal with a this pointer
437  */
438  void propertyChangeNotifier();
439 
440  /**
441  * A set of constraints applied on this property.
442  */
443  std::shared_ptr< ConstraintContainerType > m_constraints;
444 
445 private:
446  /**
447  * This is true, if the user did not set a value until now using \ref set.
448  */
450 };
451 
452 template < typename T >
453 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial ):
454  WFlag< T >( new WCondition(), initial ),
455  WPropertyBase( name, description ),
456  m_constraints( new ConstraintContainerType() ),
457  m_notYetSet( true )
458 {
459  updateType();
460 
461  // set constraint and change condition to update condition set of WPropertyBase
462  m_updateCondition->add( m_constraints->getChangeCondition() );
464 }
465 
466 template < typename T >
467 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial, std::shared_ptr< WCondition > condition ):
468  WFlag< T >( condition, initial ),
469  WPropertyBase( name, description ),
470  m_constraints( new ConstraintContainerType() ),
471  m_notYetSet( true )
472 {
473  updateType();
474 
475  // set constraint and change condition to update condition set of WPropertyBase
476  m_updateCondition->add( m_constraints->getChangeCondition() );
478 }
479 
480 template < typename T >
481 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial,
482  PropertyChangeNotifierType notifier ):
483  WFlag< T >( new WCondition(), initial ),
484  WPropertyBase( name, description ),
485  m_constraints( new ConstraintContainerType() ),
486  m_notYetSet( true )
487 {
488  updateType();
489 
490  // set constraint and change condition to update condition set of WPropertyBase
491  m_updateCondition->add( m_constraints->getChangeCondition() );
493 
494  // set custom notifier
497  );
498  signal_PropertyChange.connect( notifier );
499 }
500 
501 template < typename T >
502 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial, std::shared_ptr< WCondition > condition,
503  PropertyChangeNotifierType notifier ):
504  WFlag< T >( condition, initial ),
505  WPropertyBase( name, description ),
506  m_constraints( new ConstraintContainerType() ),
507  m_notYetSet( true )
508 {
509  updateType();
510 
511  // set constraint and change condition to update condition set of WPropertyBase
512  m_updateCondition->add( m_constraints->getChangeCondition() );
514 
515  // set custom notifier
518  );
519  signal_PropertyChange.connect( notifier );
520 }
521 
522 template < typename T >
524  WFlag< T >( from ),
525  WPropertyBase( from ),
526  m_constraints( new ConstraintContainerType() ),
527  m_notYetSet( from.m_notYetSet )
528 {
529  // copy the constraints
530 
531  // lock, unlocked if l looses focus
533  const_cast< WPropertyVariable< T >& >( from ).m_constraints->getReadTicket();
534 
535  // get write ticket too
537 
538  // we need to make a deep copy here.
539  for( typename ConstraintContainerType::ConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
540  {
541  // clone them to keep dynamic type
542  w->get().insert( ( *iter )->clone() );
543  }
544 
545  // set constraint and change condition to update condition set of WPropertyBase
546  m_updateCondition->add( m_constraints->getChangeCondition() );
548 }
549 
550 template < typename T >
552 {
553  // clean up
554  m_updateCondition->remove( m_constraints->getChangeCondition() );
555  m_updateCondition->remove( WFlag< T >::getValueChangeCondition() );
556 
557  m_notifierConnection.disconnect();
558 
559  // lock, unlocked if l looses focus
560  typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
561  l->get().clear();
562 }
563 
564 template < typename T >
565 std::shared_ptr< WPropertyBase > WPropertyVariable< T >::clone()
566 {
567  return std::shared_ptr< WPropertyBase >( new WPropertyVariable< T >( *this ) );
568 }
569 
570 template < typename T >
572 {
573  // propagate change, include pointer to property
574  signal_PropertyChange( shared_from_this() );
575 }
576 
577 template < typename T >
578 bool WPropertyVariable< T >::accept( const T& newValue )
579 {
580  // lock, lock vanishes if l looses focus
581  typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l = m_constraints->getReadTicket();
582 
583  // iterate through the set
584  bool acceptable = WFlag< T >::accept( newValue );
585  for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); ++it )
586  {
587  acceptable &= ( *it )->accept( std::static_pointer_cast< WPropertyVariable< T > >( shared_from_this() ), newValue );
588  }
589 
590  return acceptable;
591 }
592 
593 template < typename T >
594 bool WPropertyVariable< T >::setAsString( std::string value )
595 {
596  try
597  {
598  // use the helper class which can handle different kinds of properties for us
600  return set( h.create( WFlag< T >::get(), value ) );
601  }
602  catch( const std::exception &e )
603  {
604  return false;
605  }
606 }
607 
608 template < typename T >
610 {
611  std::string val;
612  // use the helper class which can handle different kinds of properties for us
614  return h.asString( WFlag< T >::get() );
615 
616  return val;
617 }
618 
619 template < typename T >
620 bool WPropertyVariable< T >::set( std::shared_ptr< WPropertyBase > value, bool recommendedOnly )
621 {
622  // try to cast the given property to a WPropertyVariable of right type:
623  std::shared_ptr< WPropertyVariable< T > > v = std::dynamic_pointer_cast< WPropertyVariable< T > >( value );
624  if( v )
625  {
626  if( recommendedOnly )
627  {
628  return setRecommendedValue( v->get() );
629  }
630  else
631  {
632  return set( v->get() );
633  }
634  }
635  else
636  {
637  return false;
638  }
639 }
640 
641 template < typename T >
642 bool WPropertyVariable< T >::set( const T& value, bool suppressNotification )
643 {
644  m_notYetSet = false;
645  return WFlag< T >::set( value, suppressNotification );
646 }
647 
648 template < typename T >
650 {
651  // NOTE: well this is quite problematic when used multi-threaded ...
652  if( m_notYetSet )
653  {
654  bool ret = set( value );
655  m_notYetSet = true;
656  return ret;
657  }
658  else
659  {
660  return false;
661  }
662 }
663 
664 template < typename T >
665 bool WPropertyVariable< T >::ensureValidity( const T& newValidValue, bool suppressNotification )
666 {
667  if( !accept( WFlag< T >::get() ) )
668  {
669  // the currently set constraints forbid the current value.
670  // reset it to the new value
671  return WFlag< T >::set( newValidValue, suppressNotification );
672  }
673 
674  return true;
675 }
676 
677 template < typename T >
678 void WPropertyVariable< T >::addConstraint( std::shared_ptr< PropertyConstraint > constraint )
679 {
680  // lock, unlocked if l looses focus
681  typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
682  l->get().insert( constraint );
683 
684  // unlock by hand
685  l.reset();
686 }
687 
688 template < typename T >
690 {
691  return m_constraints->getChangeCondition();
692 }
693 
694 template < typename T >
696 {
698  m_type = tid.getType();
699 }
700 
701 template < typename T >
702 std::shared_ptr< WPropertyConstraintMin< T > > WPropertyVariable< T >::minConstraint( const T& min )
703 {
704  return std::shared_ptr< WPropertyConstraintMin< T > >( new WPropertyConstraintMin< T >( min ) );
705 }
706 
707 template < typename T >
708 std::shared_ptr< WPropertyConstraintMax< T > > WPropertyVariable< T >::maxConstraint( const T& max )
709 {
710  return std::shared_ptr< WPropertyConstraintMax< T > >( new WPropertyConstraintMax< T >( max ) );
711 }
712 
713 template < typename T >
714 std::shared_ptr< WPropertyConstraintMin< T > > WPropertyVariable< T >::setMin( const T& min )
715 {
716  std::shared_ptr< WPropertyConstraintMin< T > > c = minConstraint( min );
717  replaceConstraint( c, PC_MIN );
718  return c;
719 }
720 
721 template < typename T >
722 std::shared_ptr< WPropertyConstraintMax< T > > WPropertyVariable< T >::setMax( const T& max )
723 {
724  std::shared_ptr< WPropertyConstraintMax< T > > c = maxConstraint( max );
725  replaceConstraint( c, PC_MAX );
726  return c;
727 }
728 
729 template < typename T >
730 void WPropertyVariable< T >::replaceConstraint( std::shared_ptr< PropertyConstraint > constraint, PROPERTYCONSTRAINT_TYPE type )
731 {
732  // lock, unlocked if l looses focus
733  typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
734 
735  removeConstraints( type, l );
736  l->get().insert( constraint );
737 }
738 
739 template < typename T >
740 std::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >
741 WPropertyVariable< T >::replaceConstraint( PROPERTYCONSTRAINT_TYPE constraint, PROPERTYCONSTRAINT_TYPE type )
742 {
743  std::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > c = PropertyConstraint::create( constraint );
744  replaceConstraint( c, type );
745  return c;
746 }
747 
748 template < typename T >
749 std::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >
750 WPropertyVariable< T >::getFirstConstraint( PROPERTYCONSTRAINT_TYPE type )
751 {
752  // lock, unlocked if l looses focus
753  typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l = m_constraints->getReadTicket();
754 
755  // search first appearance of a constraint of the specified type
756  for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); ++it )
757  {
758  if( ( *it )->getType() == type )
759  {
760  return ( *it );
761  }
762  }
763 
764  return std::shared_ptr< PropertyConstraint >();
765 }
766 
767 template < typename T >
768 int WPropertyVariable< T >::countConstraint( PROPERTYCONSTRAINT_TYPE type )
769 {
770  // lock, unlocked if l looses focus
771  typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l = m_constraints->getReadTicket();
772 
773  int i = 0;
774  // search first appearance of a constraint of the specified type
775  for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); ++it )
776  {
777  if( ( *it )->getType() == type )
778  {
779  i++;
780  }
781  }
782 
783  return i;
784 }
785 
786 template < typename T >
787 std::shared_ptr< WPropertyConstraintMin< T > > WPropertyVariable< T >::getMin()
788 {
789  // get min
790  std::shared_ptr< PropertyConstraint > c = getFirstConstraint( PC_MIN );
791  if( !c.get() )
792  {
793  // return NULL if not found
794  return std::shared_ptr< WPropertyConstraintMin< T > >();
795  }
796 
797  // cast to proper type
798  return std::static_pointer_cast< WPropertyConstraintMin< T > >( c );
799 }
800 
801 template < typename T >
802 std::shared_ptr< WPropertyConstraintMax< T > > WPropertyVariable< T >::getMax()
803 {
804  // get min
805  std::shared_ptr< PropertyConstraint > c = getFirstConstraint( PC_MAX );
806  if( !c.get() )
807  {
808  // return NULL if not found
809  return std::shared_ptr< WPropertyConstraintMax< T > >();
810  }
811 
812  // cast to proper type
813  return std::static_pointer_cast< WPropertyConstraintMax< T > >( c );
814 }
815 
816 template< typename T >
818 {
819  return m_constraints;
820 }
821 
822 template < typename T >
823 void WPropertyVariable< T >::removeConstraints( PROPERTYCONSTRAINT_TYPE type,
825 {
827 
828  bool useLock = !ticket;
829 
830  // lock the constraints set
831  if( useLock )
832  {
833  // lock, unlocked if l looses focus
834  l = m_constraints->getWriteTicket();
835  }
836 
837  size_t nbErased = 0; // count how much items have been removed
838  for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); )
839  {
840  if( ( *it )->getType() == type )
841  {
842  l->get().erase( it++ );
843  ++nbErased;
844  }
845  else
846  {
847  ++it;
848  }
849  }
850 
851  // only notify and unlock if locked earlier.
852  if( useLock )
853  {
854  // no operations done? No condition fired
855  if( nbErased == 0 )
856  {
857  l->suppressUnlockCondition();
858  }
859 
860  // unlock by hand
861  l.reset();
862  }
863 }
864 
865 template < typename T >
866 void WPropertyVariable< T >::removeConstraint( PROPERTYCONSTRAINT_TYPE type )
867 {
868  // simply forward the call
869  removeConstraints( type, typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket() );
870 }
871 
872 template < typename T >
873 void WPropertyVariable< T >::removeConstraint( std::shared_ptr< PropertyConstraint > constraint )
874 {
875  // lock released automatically
876  typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
877 
878  if( l->get().erase( constraint ) == 0 )
879  {
880  // nothing changed. Suppress update condition to fire
881  l->suppressUnlockCondition();
882  }
883 }
884 
885 template < typename T >
887 {
888 }
889 
890 template < typename T >
892 {
893 }
894 
895 template < typename T >
897 {
898  return PC_UNKNOWN;
899 }
900 
901 #endif // WPROPERTYVARIABLE_H
Class helping to create a new instance of the property content from an old one.
T create(const T &, const std::string str)
Creates a new instance of the type from a given string.
std::string asString(const T &v)
Creates a string from the specified value.
Class helping to adapt types specified as template parameter into an enum.
PROPERTY_TYPE getType()
Get type identifier of the template type T.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
Class to have a simple notification/condition system for simple flags.
Definition: WFlag.h:39
virtual bool accept(const T &newValue)
Determines whether the specified value is acceptable.
Definition: WFlag.h:331
virtual const T & get(bool resetChangeState=false)
Operator returns value of the flag.
Definition: WFlag.h:257
std::shared_ptr< WCondition > getValueChangeCondition()
Returns the condition denoting a value change.
Definition: WFlag.h:325
virtual bool set(const T &value, bool suppressNotification=false)
Sets the new value for this flag.
Definition: WFlag.h:291
Abstract base class for all properties.
Definition: WPropertyBase.h:48
std::shared_ptr< WConditionSet > m_updateCondition
Condition notified whenever something changes.
PropertyChangeSignalType signal_PropertyChange
Signal getting fired whenever the property changes.
boost::function< void(std::shared_ptr< WPropertyBase >)> PropertyChangeNotifierType
Signal signature emitted during set operations.
This class allows constraining properties using a maximum value and the corresponding <= operator.
This class allows constraining properties using a minimum value and the corresponding >= operator.
Test WPropertyVariable.
Class building the base for user defined constraints on a property instance.
virtual PROPERTYCONSTRAINT_TYPE getType()
Allows simple identification of the real constraint type.
virtual bool accept(std::shared_ptr< WPropertyVariable< T > > property, const T &value)=0
This method decides whether the specified value is valid for a specific property.
virtual std::shared_ptr< PropertyConstraint > clone()=0
Method to clone the constraint and create a new one with the correct dynamic type.
static std::shared_ptr< PropertyConstraint > create(PROPERTYCONSTRAINT_TYPE type)
This method creates a constraint using the specified type.
A named property class with a concrete type.
virtual bool setRecommendedValue(const T &value)
Sets the specified value as recommended value.
virtual bool setAsString(std::string value)
This methods allows properties to be set by a string value.
void addConstraint(std::shared_ptr< PropertyConstraint > constraint)
Add a new constraint.
PropertyConstraintMin setMin(const T &min)
Set a minimum constraint.
virtual ~WPropertyVariable()
Destructor.
virtual bool ensureValidity(const T &newValidValue, bool suppressNotification=false)
This method is useful to ensure, that there is a valid value in the property.
virtual std::shared_ptr< WPropertyBase > clone()
This method clones a property and returns the clone.
PropertyConstraintMax setMax(const T &max)
Set a maximum constraint.
boost::signals2::connection m_notifierConnection
The connection used for notification.
std::shared_ptr< WPropertyConstraintMin< T > > PropertyConstraintMin
Alias for min constraints.
std::shared_ptr< WPropertyConstraintMax< T > > PropertyConstraintMax
Alias for max constraints.
PropertyConstraintMin getMin()
Gets the current minimum constraint value.
bool m_notYetSet
This is true, if the user did not set a value until now using set.
void replaceConstraint(std::shared_ptr< PropertyConstraint > constraint, PROPERTYCONSTRAINT_TYPE type)
This replaces all existing constraints of a certain type by a new specified constraint.
void propertyChangeNotifier()
This method gets called by WFlag whenever the value of the property changes.
virtual std::string getAsString()
Returns the current value as a string.
T DataType
The type of the data of this property.
PropertyConstraintMax getMax()
Gets the current maximum constraint value.
ConstraintContainerType getConstraints()
Returns all the current constraints of a WPropertyVariable.
WSharedAssociativeContainer< std::set< std::shared_ptr< PropertyConstraint > > > ConstraintContainerType
The alias for a shared container.
static PropertyConstraintMin minConstraint(const T &min)
Creates a new WPropertyConstraintMin for this WPropertyVariable.
void removeConstraints(PROPERTYCONSTRAINT_TYPE type, typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket ticket=ConstraintContainerType::WriteTicket())
Cleans list of constraints from all existing constrains of the specified type.
void removeConstraint(PROPERTYCONSTRAINT_TYPE type)
Cleans list of constraints from all existing constrains of the specified type.
std::shared_ptr< const WPropertyVariable< T > > ConstSPtr
Convenience typedef for a shared_ptr of const WPropertyVariable.
std::shared_ptr< PropertyConstraint > getFirstConstraint(PROPERTYCONSTRAINT_TYPE type)
Method searching the first appearance of a constrained with the specified type.
static PropertyConstraintMax maxConstraint(const T &max)
Creates a new WPropertyConstraintMax for this WPropertyVariable.
virtual void updateType()
Uses typeid() to set the proper type constant.
virtual bool accept(const T &newValue)
Determines whether the specified value is acceptable.
virtual bool set(std::shared_ptr< WPropertyBase > value, bool recommendedOnly=false)
Sets the value from the specified property to this one.
WPropertyVariable(std::string name, std::string description, const T &initial)
Create an empty instance just containing a name.
std::shared_ptr< WCondition > getContraintsChangedCondition()
Gets the condition, which gets notified whenever the list of constraints changes.
std::shared_ptr< WPropertyVariable< T > > SPtr
Convenience typedef for a shared_ptr of WPropertyVariable.
int countConstraint(PROPERTYCONSTRAINT_TYPE type)
Method searching the first appearance of a constrained with the specified type.
std::shared_ptr< ConstraintContainerType > m_constraints
A set of constraints applied on this property.
This class provides a common interface for thread-safe access to associative containers (set,...
T::const_iterator ConstIterator
A typedef for the correct const iterator useful to traverse this sequence container.
std::shared_ptr< WSharedObjectTicketRead< T > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
std::shared_ptr< WSharedObjectTicketWrite< T > > WriteTicket
Type for write tickets.
Definition: WSharedObject.h:70