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