00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef WPROPERTYVARIABLE_H
00026 #define WPROPERTYVARIABLE_H
00027
00028 #include <stdint.h>
00029
00030 #include <iostream>
00031 #include <list>
00032 #include <set>
00033 #include <string>
00034 #include <vector>
00035
00036
00037 #ifndef BOOST_FILESYSTEM_VERSION
00038 #define BOOST_FILESYSTEM_VERSION 2
00039 #endif
00040 #include <boost/filesystem.hpp>
00041 #include <boost/lexical_cast.hpp>
00042 #include <boost/thread.hpp>
00043
00044 #include "constraints/WPropertyConstraintIsDirectory.h"
00045 #include "constraints/WPropertyConstraintMax.h"
00046 #include "constraints/WPropertyConstraintMin.h"
00047 #include "constraints/WPropertyConstraintNotEmpty.h"
00048 #include "constraints/WPropertyConstraintPathExists.h"
00049 #include "constraints/WPropertyConstraintSelectOnlyOne.h"
00050 #include "constraints/WPropertyConstraintTypes.h"
00051 #include "WCondition.h"
00052 #include "WFlag.h"
00053 #include "WLogger.h"
00054 #include "WPropertyBase.h"
00055 #include "WSharedAssociativeContainer.h"
00056 #include "WSharedObjectTicketRead.h"
00057 #include "WSharedObjectTicketWrite.h"
00058
00059
00060
00061
00062 template< typename T >
00063 class WPropertyVariable: public WFlag< T >,
00064 public WPropertyBase
00065 {
00066 friend class WPropertyVariableTest;
00067 public:
00068
00069
00070
00071 typedef boost::shared_ptr< WPropertyVariable< T > > SPtr;
00072
00073
00074
00075
00076 typedef boost::shared_ptr< const WPropertyVariable< T > > ConstSPtr;
00077
00078
00079
00080
00081
00082
00083
00084
00085 WPropertyVariable( std::string name, std::string description, const T& initial );
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 WPropertyVariable( std::string name, std::string description, const T& initial, boost::shared_ptr< WCondition > condition );
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 WPropertyVariable( std::string name, std::string description, const T& initial, PropertyChangeNotifierType notifier );
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 WPropertyVariable( std::string name, std::string description, const T& initial, boost::shared_ptr< WCondition > condition,
00128 PropertyChangeNotifierType notifier );
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 explicit WPropertyVariable( const WPropertyVariable< T >& from );
00140
00141
00142
00143
00144 virtual ~WPropertyVariable();
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 virtual boost::shared_ptr< WPropertyBase > clone();
00156
00157
00158
00159
00160
00161
00162
00163
00164 virtual bool accept( T newValue );
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 virtual bool ensureValidity( T newValidValue, bool suppressNotification = false );
00178
00179
00180
00181
00182 class PropertyConstraint
00183 {
00184 public:
00185
00186
00187
00188
00189 PropertyConstraint();
00190
00191
00192
00193
00194 virtual ~PropertyConstraint();
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 virtual bool accept( boost::shared_ptr< WPropertyVariable< T > > property, T value ) = 0;
00205
00206
00207
00208
00209
00210
00211 virtual PROPERTYCONSTRAINT_TYPE getType();
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 static boost::shared_ptr< PropertyConstraint > create( PROPERTYCONSTRAINT_TYPE type );
00222
00223
00224
00225
00226
00227
00228 virtual boost::shared_ptr< PropertyConstraint > clone() = 0;
00229 };
00230
00231
00232
00233
00234 typedef WSharedAssociativeContainer< std::set< boost::shared_ptr< PropertyConstraint > > > ConstraintContainerType;
00235
00236
00237
00238
00239 typedef boost::shared_ptr< WPropertyConstraintMin< T > > PropertyConstraintMin;
00240
00241
00242
00243
00244 typedef boost::shared_ptr< WPropertyConstraintMax< T > > PropertyConstraintMax;
00245
00246
00247
00248
00249
00250
00251
00252 void addConstraint( boost::shared_ptr< PropertyConstraint > constraint );
00253
00254
00255
00256
00257
00258
00259 ConstraintContainerType getConstraints();
00260
00261
00262
00263
00264
00265
00266
00267 boost::shared_ptr< WCondition > getContraintsChangedCondition();
00268
00269
00270
00271
00272
00273
00274
00275
00276 static PropertyConstraintMin minConstraint( T min );
00277
00278
00279
00280
00281
00282
00283
00284
00285 static PropertyConstraintMax maxConstraint( T max );
00286
00287
00288
00289
00290
00291
00292
00293
00294 PropertyConstraintMin setMin( T min );
00295
00296
00297
00298
00299
00300
00301
00302
00303 PropertyConstraintMax setMax( T max );
00304
00305
00306
00307
00308
00309
00310 PropertyConstraintMin getMin();
00311
00312
00313
00314
00315
00316
00317 PropertyConstraintMax getMax();
00318
00319
00320
00321
00322
00323
00324
00325 void replaceConstraint( boost::shared_ptr< PropertyConstraint > constraint, PROPERTYCONSTRAINT_TYPE type );
00326
00327
00328
00329
00330
00331
00332
00333
00334 boost::shared_ptr< PropertyConstraint > replaceConstraint( PROPERTYCONSTRAINT_TYPE constraint, PROPERTYCONSTRAINT_TYPE type );
00335
00336
00337
00338
00339
00340
00341 void removeConstraint( PROPERTYCONSTRAINT_TYPE type );
00342
00343
00344
00345
00346
00347
00348 void removeConstraint( boost::shared_ptr< PropertyConstraint > constraint );
00349
00350
00351
00352
00353
00354
00355
00356
00357 boost::shared_ptr< PropertyConstraint > getFirstConstraint( PROPERTYCONSTRAINT_TYPE type );
00358
00359
00360
00361
00362
00363
00364
00365
00366 int countConstraint( PROPERTYCONSTRAINT_TYPE type );
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 virtual bool setAsString( std::string value );
00377
00378
00379
00380
00381
00382
00383
00384 virtual std::string getAsString();
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 virtual bool set( boost::shared_ptr< WPropertyBase > value );
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 virtual bool set( T value, bool suppressNotification = false );
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 virtual bool setRecommendedValue( T value );
00419
00420 protected:
00421
00422
00423
00424
00425 boost::signals2::connection m_notifierConnection;
00426
00427
00428
00429
00430 virtual void updateType();
00431
00432
00433
00434
00435
00436
00437
00438 void removeConstraints( PROPERTYCONSTRAINT_TYPE type,
00439 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket ticket
00440 = ConstraintContainerType::WriteTicket() );
00441
00442
00443
00444
00445 void propertyChangeNotifier();
00446
00447
00448
00449
00450 boost::shared_ptr< ConstraintContainerType > m_constraints;
00451
00452 private:
00453
00454
00455
00456
00457 bool m_notYetSet;
00458 };
00459
00460 template < typename T >
00461 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial ):
00462 WFlag< T >( new WCondition(), initial ),
00463 WPropertyBase( name, description ),
00464 m_constraints( new ConstraintContainerType() ),
00465 m_notYetSet( true )
00466 {
00467 updateType();
00468
00469
00470 m_updateCondition->add( m_constraints->getChangeCondition() );
00471 m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
00472 }
00473
00474 template < typename T >
00475 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial, boost::shared_ptr< WCondition > condition ):
00476 WFlag< T >( condition, initial ),
00477 WPropertyBase( name, description ),
00478 m_constraints( new ConstraintContainerType() ),
00479 m_notYetSet( true )
00480 {
00481 updateType();
00482
00483
00484 m_updateCondition->add( m_constraints->getChangeCondition() );
00485 m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
00486 }
00487
00488 template < typename T >
00489 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial,
00490 PropertyChangeNotifierType notifier ):
00491 WFlag< T >( new WCondition(), initial ),
00492 WPropertyBase( name, description ),
00493 m_constraints( new ConstraintContainerType() ),
00494 m_notYetSet( true )
00495 {
00496 updateType();
00497
00498
00499 m_updateCondition->add( m_constraints->getChangeCondition() );
00500 m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
00501
00502
00503 m_notifierConnection = WFlag< T >::getValueChangeCondition()->subscribeSignal(
00504 boost::bind( &WPropertyVariable< T >::propertyChangeNotifier, this )
00505 );
00506 signal_PropertyChange.connect( notifier );
00507 }
00508
00509 template < typename T >
00510 WPropertyVariable< T >::WPropertyVariable( std::string name, std::string description, const T& initial, boost::shared_ptr< WCondition > condition,
00511 PropertyChangeNotifierType notifier ):
00512 WFlag< T >( condition, initial ),
00513 WPropertyBase( name, description ),
00514 m_constraints( new ConstraintContainerType() ),
00515 m_notYetSet( true )
00516 {
00517 updateType();
00518
00519
00520 m_updateCondition->add( m_constraints->getChangeCondition() );
00521 m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
00522
00523
00524 m_notifierConnection = WFlag< T >::getValueChangeCondition()->subscribeSignal(
00525 boost::bind( &WPropertyVariable< T >::propertyChangeNotifier, this )
00526 );
00527 signal_PropertyChange.connect( notifier );
00528 }
00529
00530 template < typename T >
00531 WPropertyVariable< T >::WPropertyVariable( const WPropertyVariable< T >& from ):
00532 WFlag< T >( from ),
00533 WPropertyBase( from ),
00534 m_constraints( new ConstraintContainerType() ),
00535 m_notYetSet( from.m_notYetSet )
00536 {
00537
00538
00539
00540 typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l =
00541 const_cast< WPropertyVariable< T >& >( from ).m_constraints->getReadTicket();
00542
00543
00544 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket w = m_constraints->getWriteTicket();
00545
00546
00547 for( typename ConstraintContainerType::ConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
00548 {
00549
00550 w->get().insert( ( *iter )->clone() );
00551 }
00552
00553
00554 m_updateCondition->add( m_constraints->getChangeCondition() );
00555 m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
00556 }
00557
00558 template < typename T >
00559 WPropertyVariable< T >::~WPropertyVariable()
00560 {
00561
00562 m_updateCondition->remove( m_constraints->getChangeCondition() );
00563 m_updateCondition->remove( WFlag< T >::getValueChangeCondition() );
00564
00565 m_notifierConnection.disconnect();
00566
00567
00568 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
00569 l->get().clear();
00570 }
00571
00572 template < typename T >
00573 boost::shared_ptr< WPropertyBase > WPropertyVariable< T >::clone()
00574 {
00575 return boost::shared_ptr< WPropertyBase >( new WPropertyVariable< T >( *this ) );
00576 }
00577
00578 template < typename T >
00579 void WPropertyVariable< T >::propertyChangeNotifier()
00580 {
00581
00582 signal_PropertyChange( shared_from_this() );
00583 }
00584
00585 template < typename T >
00586 bool WPropertyVariable< T >::accept( T newValue )
00587 {
00588
00589 typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l = m_constraints->getReadTicket();
00590
00591
00592 bool acceptable = WFlag< T >::accept( newValue );
00593 for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); ++it )
00594 {
00595 acceptable &= ( *it )->accept( boost::shared_static_cast< WPropertyVariable< T > >( shared_from_this() ), newValue );
00596 }
00597
00598 return acceptable;
00599 }
00600
00601 template < typename T >
00602 bool WPropertyVariable< T >::setAsString( std::string value )
00603 {
00604 try
00605 {
00606
00607 PROPERTY_TYPE_HELPER::WStringConversion< T > h = PROPERTY_TYPE_HELPER::WStringConversion< T >();
00608 return set( h.create( WFlag< T >::get(), value ) );
00609 }
00610 catch( const boost::bad_lexical_cast &e )
00611 {
00612 return false;
00613 }
00614 }
00615
00616 template < typename T >
00617 std::string WPropertyVariable< T >::getAsString()
00618 {
00619 std::string val;
00620
00621 PROPERTY_TYPE_HELPER::WStringConversion< T > h = PROPERTY_TYPE_HELPER::WStringConversion< T >();
00622 return h.asString( WFlag< T >::get() );
00623
00624 return val;
00625 }
00626
00627 template < typename T >
00628 bool WPropertyVariable< T >::set( boost::shared_ptr< WPropertyBase > value )
00629 {
00630
00631 boost::shared_ptr< WPropertyVariable< T > > v = boost::shared_dynamic_cast< WPropertyVariable< T > >( value );
00632 if( v )
00633 {
00634 return set( v->get() );
00635 }
00636 else
00637 {
00638 return false;
00639 }
00640 }
00641
00642 template < typename T >
00643 bool WPropertyVariable< T >::set( T value, bool suppressNotification )
00644 {
00645 m_notYetSet = false;
00646 return WFlag< T >::set( value, suppressNotification );
00647 }
00648
00649 template < typename T >
00650 bool WPropertyVariable< T >::setRecommendedValue( T value )
00651 {
00652
00653 if( m_notYetSet )
00654 {
00655 bool ret = set( value );
00656 m_notYetSet = true;
00657 return ret;
00658 }
00659 else
00660 {
00661 return false;
00662 }
00663 }
00664
00665 template < typename T >
00666 bool WPropertyVariable< T >::ensureValidity( T newValidValue, bool suppressNotification )
00667 {
00668 if( !accept( WFlag< T >::get() ) )
00669 {
00670
00671
00672 return WFlag< T >::set( newValidValue, suppressNotification );
00673 }
00674
00675 return true;
00676 }
00677
00678 template < typename T >
00679 void WPropertyVariable< T >::addConstraint( boost::shared_ptr< PropertyConstraint > constraint )
00680 {
00681
00682 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
00683 l->get().insert( constraint );
00684
00685
00686 l.reset();
00687 }
00688
00689 template < typename T >
00690 boost::shared_ptr< WCondition > WPropertyVariable< T >::getContraintsChangedCondition()
00691 {
00692 return m_constraints->getChangeCondition();
00693 }
00694
00695 template < typename T >
00696 void WPropertyVariable< T >::updateType()
00697 {
00698 PROPERTY_TYPE_HELPER::WTypeIdentifier< T > tid;
00699 m_type = tid.getType();
00700 }
00701
00702 template < typename T >
00703 boost::shared_ptr< WPropertyConstraintMin< T > > WPropertyVariable< T >::minConstraint( T min )
00704 {
00705 return boost::shared_ptr< WPropertyConstraintMin< T > >( new WPropertyConstraintMin< T >( min ) );
00706 }
00707
00708 template < typename T >
00709 boost::shared_ptr< WPropertyConstraintMax< T > > WPropertyVariable< T >::maxConstraint( T max )
00710 {
00711 return boost::shared_ptr< WPropertyConstraintMax< T > >( new WPropertyConstraintMax< T >( max ) );
00712 }
00713
00714 template < typename T >
00715 boost::shared_ptr< WPropertyConstraintMin< T > > WPropertyVariable< T >::setMin( T min )
00716 {
00717 boost::shared_ptr< WPropertyConstraintMin< T > > c = minConstraint( min );
00718 replaceConstraint( c, PC_MIN );
00719 return c;
00720 }
00721
00722 template < typename T >
00723 boost::shared_ptr< WPropertyConstraintMax< T > > WPropertyVariable< T >::setMax( T max )
00724 {
00725 boost::shared_ptr< WPropertyConstraintMax< T > > c = maxConstraint( max );
00726 replaceConstraint( c, PC_MAX );
00727 return c;
00728 }
00729
00730 template < typename T >
00731 void WPropertyVariable< T >::replaceConstraint( boost::shared_ptr< PropertyConstraint > constraint, PROPERTYCONSTRAINT_TYPE type )
00732 {
00733
00734 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
00735
00736 removeConstraints( type, l );
00737 l->get().insert( constraint );
00738 }
00739
00740 template < typename T >
00741 boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >
00742 WPropertyVariable< T >::replaceConstraint( PROPERTYCONSTRAINT_TYPE constraint, PROPERTYCONSTRAINT_TYPE type )
00743 {
00744 boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > c = PropertyConstraint::create( constraint );
00745 replaceConstraint( c, type );
00746 return c;
00747 }
00748
00749 template < typename T >
00750 boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >
00751 WPropertyVariable< T >::getFirstConstraint( PROPERTYCONSTRAINT_TYPE type )
00752 {
00753
00754 typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l = m_constraints->getReadTicket();
00755
00756
00757 for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); ++it )
00758 {
00759 if( ( *it )->getType() == type )
00760 {
00761 return ( *it );
00762 }
00763 }
00764
00765 return boost::shared_ptr< PropertyConstraint >();
00766 }
00767
00768 template < typename T >
00769 int WPropertyVariable< T >::countConstraint( PROPERTYCONSTRAINT_TYPE type )
00770 {
00771
00772 typename WPropertyVariable< T >::ConstraintContainerType::ReadTicket l = m_constraints->getReadTicket();
00773
00774 int i = 0;
00775
00776 for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); ++it )
00777 {
00778 if( ( *it )->getType() == type )
00779 {
00780 i++;
00781 }
00782 }
00783
00784 return i;
00785 }
00786
00787 template < typename T >
00788 boost::shared_ptr< WPropertyConstraintMin< T > > WPropertyVariable< T >::getMin()
00789 {
00790
00791 boost::shared_ptr< PropertyConstraint > c = getFirstConstraint( PC_MIN );
00792 if( !c.get() )
00793 {
00794
00795 return boost::shared_ptr< WPropertyConstraintMin< T > >();
00796 }
00797
00798
00799 return boost::shared_static_cast< WPropertyConstraintMin< T > >( c );
00800 }
00801
00802 template < typename T >
00803 boost::shared_ptr< WPropertyConstraintMax< T > > WPropertyVariable< T >::getMax()
00804 {
00805
00806 boost::shared_ptr< PropertyConstraint > c = getFirstConstraint( PC_MAX );
00807 if( !c.get() )
00808 {
00809
00810 return boost::shared_ptr< WPropertyConstraintMax< T > >();
00811 }
00812
00813
00814 return boost::shared_static_cast< WPropertyConstraintMax< T > >( c );
00815 }
00816
00817 template< typename T >
00818 typename WPropertyVariable<T>::ConstraintContainerType WPropertyVariable<T>::getConstraints()
00819 {
00820 return m_constraints;
00821 }
00822
00823 template < typename T >
00824 void WPropertyVariable< T >::removeConstraints( PROPERTYCONSTRAINT_TYPE type,
00825 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket ticket )
00826 {
00827 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = ticket;
00828
00829 bool useLock = !ticket;
00830
00831
00832 if( useLock )
00833 {
00834
00835 l = m_constraints->getWriteTicket();
00836 }
00837
00838 size_t nbErased = 0;
00839 for( typename ConstraintContainerType::ConstIterator it = l->get().begin(); it != l->get().end(); )
00840 {
00841 if( ( *it )->getType() == type )
00842 {
00843 l->get().erase( it++ );
00844 ++nbErased;
00845 }
00846 else
00847 {
00848 ++it;
00849 }
00850 }
00851
00852
00853 if( useLock )
00854 {
00855
00856 if( nbErased == 0 )
00857 {
00858 l->suppressUnlockCondition();
00859 }
00860
00861
00862 l.reset();
00863 }
00864 }
00865
00866 template < typename T >
00867 void WPropertyVariable< T >::removeConstraint( PROPERTYCONSTRAINT_TYPE type )
00868 {
00869
00870 removeConstraints( type, typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket() );
00871 }
00872
00873 template < typename T >
00874 void WPropertyVariable< T >::removeConstraint( boost::shared_ptr< PropertyConstraint > constraint )
00875 {
00876
00877 typename WPropertyVariable< T >::ConstraintContainerType::WriteTicket l = m_constraints->getWriteTicket();
00878
00879 if( l->get().erase( constraint ) == 0 )
00880 {
00881
00882 l->suppressUnlockCondition();
00883 }
00884 }
00885
00886 template < typename T >
00887 WPropertyVariable< T >::PropertyConstraint::PropertyConstraint()
00888 {
00889 }
00890
00891 template < typename T >
00892 WPropertyVariable< T >::PropertyConstraint::~PropertyConstraint()
00893 {
00894 }
00895
00896 template < typename T >
00897 PROPERTYCONSTRAINT_TYPE WPropertyVariable< T >::PropertyConstraint::getType()
00898 {
00899 return PC_UNKNOWN;
00900 }
00901
00902 #endif // WPROPERTYVARIABLE_H
00903