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