Changeset 942 for library/bdm/base/user_info.h
- Timestamp:
- 05/14/10 12:16:00 (14 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
library/bdm/base/user_info.h
r927 r942 228 228 }; 229 229 230 231 //! This class stores the details which will be logged to a logger 232 //! 233 //! This is only the first part of the whole declaration, which has to be however separated into 234 //! two different classes for allowing the compilation of source code. For more details 235 //! see logger::add_setting(...) method and mainly log_level_template<T>::template<class U> void store( const enum T::log_level_enums log_level_enum, const U data ) const 236 //! method. For the reason the second one is templated, it was necessary to declare this whole class. 237 template<class T> class log_level_base : public root { 238 private: 239 //! this is necessary to allow logger to set ids vector appropriately and also to set registered_logger 240 friend class logger; 241 242 protected: 243 //! boolean flags related indicating which details will be logged to a logger 244 bitset<32> values; 245 246 //! vector of vectors of log IDs - one element for each entry and multiple entries can be stored on the position of one enum 247 Vec<ivec> ids; 248 249 //! internal pointer to the logger to which this log_level is registered 250 //! 251 //! it is set to NULL at the beginning 252 logger * registered_logger; 253 254 public: 255 256 //! default constructor 257 log_level_base( ) { 258 registered_logger = NULL; 259 int len = names().length(); 260 ids.set_size( len ); 261 for( int i = 0; i<len; i++ ) 262 { 263 ids(i).set_size ( 1 ); 264 ids(i) = -1; 265 } 266 } 267 268 //! a general utility transforming a comma-separated sequence of strings into an instance of Array<strings> 269 static Array<string> string2Array( const string &input ) 270 { 271 string result = input; 272 string::size_type loc; 273 while( loc = result.find( ',' ), loc != string::npos ) 274 result[loc] = ' '; 275 return Array<string>("{ " + result + " }" ); 276 } 277 278 279 280 //! Set log_levels according to the Setting element 281 void from_setting ( const Setting &element ) 282 { 283 string raw_log_level; 284 UI::get( raw_log_level, element ); 285 Array<string> loaded_log_level = log_level_base::string2Array( raw_log_level ); 286 287 values.reset(); 288 289 for( int i = 0; i < loaded_log_level.length(); i++ ) 290 for( int j = 0; j < names().length(); j++ ){ 291 if( loaded_log_level(i) == names()(j) ) 292 { 293 values[j] = true; 294 break; 295 } 296 } 297 } 298 299 //! Store log_levels into the Setting element 300 void to_setting ( Setting &element ) const 301 { 302 // HERE WE WANT NOT TO DELETE PREVIOUS DATA STORED BY OTHER LOG_LEVELS, SEE SPECIAL IMPLEMENTATION OF UI::GET(...) FOR THIS CLASS 303 string string_to_write = ( const char* ) element; 304 305 for( unsigned int i = 0; i < values.size(); i++ ) 306 if( values[i] ) 307 { 308 if( string_to_write.length() > 0 ) 309 string_to_write = string_to_write + ','; 310 string_to_write = string_to_write + names()(i); 311 } 312 313 element = string_to_write; 314 } 315 316 //! this method adds new id to its proper position and return the name of this position 317 string store_id_and_give_name( enum T::log_level_enums const log_level_enum, int enum_subindex, int id ) { 318 if( ids(log_level_enum).length() <= enum_subindex ) 319 ids(log_level_enum).set_size( enum_subindex+1, true ); 320 ids(log_level_enum)(enum_subindex) = id; 321 322 // here we remove a "log" prefix from name, i.e., for instance it transforms "logevidence" to "evidence" 323 ostringstream stream; 324 string name_with_prefix = names()(log_level_enum); 325 string possible_log_prefix = name_with_prefix.substr(0,3); 326 if( possible_log_prefix == "log" ) 327 stream << name_with_prefix.substr(3,name_with_prefix.length()-3); 328 else 329 stream << name_with_prefix; 330 331 // add number to name only in the case there are more registered vectors with the same log_level_enum 332 if( ids(log_level_enum).length() > 1 ) 333 stream << "*" << enum_subindex; 334 335 return stream.str(); 336 } 337 338 //! string equivalents of the used enumerations which are filled with a help of #LOG_LEVEL macro within class T 339 const Array<string> &names() const 340 { 341 return T::log_level_names(); 342 } 343 344 //! read only operator for testing individual fields of log_level 345 //! 346 //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe 347 bool operator [] (const enum T::log_level_enums &log_level_enum ) const 348 { 349 return values[log_level_enum]; 350 } 351 352 //! operator for setting an individual field of log_level 353 //! 354 //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe 355 bitset<32>::reference operator [] (const enum T::log_level_enums &log_level_enum ) 356 { 357 return values[log_level_enum]; 358 } 359 }; 360 //UIREGISTER IS FORBIDDEN FOR THIS CLASS, AS IT SHOULD BE LOADED ONLY THROUGH THE SPECIALIZED UI::GET(...) METHOD 361 230 362 /*! 231 363 @brief UI is an abstract class which collects all the auxiliary functions useful to prepare some concrete … … 292 424 static const Setting& to_child_setting ( const Setting &element, const string &name ); 293 425 426 //! A shortcut for calling instance.from_setting( set ); with some error catches added 427 static void call_from_setting( root &instance, const Setting &set, string class_name = "unknown"); 428 429 //! A shortcut for calling instance.to_setting( set ); with some error catches added 430 static void call_to_setting( const root &instance, Setting &set, string class_name = "unknown" ); 431 294 432 //! This method converts a Setting into a matrix 295 433 static void from_setting ( mat& matrix, const Setting &element ); … … 304 442 //! This method converts a Setting into a real scalar 305 443 static void from_setting ( double &real, const Setting &element ); 306 //! This method converts a Setting into a log_level variant and initialize options properly 307 static void from_setting ( log_level_base &log_level, const Setting &element ); 308 444 //! This method converts a Setting into a class T descendant 445 static void from_setting ( root &instance, const Setting &element ); 309 446 //! This method converts a Setting into a class T descendant 310 447 template<class T> static void from_setting ( T* &instance, const Setting &element ) { … … 330 467 331 468 try { 332 instance->from_setting ( link.result ); 333 } catch ( SettingException &sttng_xcptn ) { 334 delete instance; 335 instance = 0; 336 string msg = "UIException: method "; 337 msg += class_name; 338 msg += ".from_setting(Setting&) has thrown a SettingException."; 339 throw UISettingException ( msg, sttng_xcptn.getPath() ); 340 } catch ( std::runtime_error &e ) { 341 delete instance; 342 instance = 0; 343 string msg = "UIException: method "; 344 msg += class_name; 345 msg += " says: "; 346 msg += e.what(); 347 throw UISettingException ( msg, link.result ); 469 call_from_setting( *instance, link.result, class_name ); 348 470 } catch ( ... ) { 349 471 delete instance; … … 351 473 throw; 352 474 } 353 354 // validate the new instance355 instance->validate();356 475 } 357 476 358 477 //! This method converts a Setting into a descendant of class 359 478 //! T, wrapped in an instance of bdm::shared_ptr<T> . 360 template<class T> 361 static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { 479 template<class T> static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { 362 480 T *tmp_inst = 0; 363 481 from_setting ( tmp_inst, element ); … … 372 490 assert_type ( link.result, Setting::TypeList ); 373 491 374 375 492 int len = link.result.getLength(); 376 493 array_to_load.set_length ( len ); … … 380 497 from_setting ( array_to_load ( i ), link.result[i] ); 381 498 } 382 /*383 //! This is dummy version of the from_setting method for other, unsupported types. It just throws an exception.384 //!385 //! At the moment, this is the only way how to compile the library without obtaining the compiler error c2665.386 //! The exception can help to find the place where the template is misused and also to correct it.387 template<class T> static void from_setting ( T &variable_to_load, const Setting &element ) {388 std::string msg = "UIException: from_setting is not implemented for type ";389 try{390 variable_to_load.from_setting(element);391 } catch (...){392 msg += typeid ( T ).name();393 msg += '.';394 throw UISettingException ( msg, element );395 }396 }397 */398 499 399 500 protected: … … 414 515 //! The new instance of type T* is constructed and initialized with values stored in the Setting element[name] 415 516 //! 416 //! If there is not any sub-element named #name and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found).517 //! If there does not exist any sub-element named #name and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). 417 518 template<class T> 418 519 static bdm::shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) { … … 431 532 //! The new instance of type T* is constructed and initialized with values stored in the Setting element[index] 432 533 //! 433 //! If there is notany sub-element indexed by #index, and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found).534 //! If there does not exist any sub-element indexed by #index, and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). 434 535 template<class T> 435 536 static bdm::shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) { … … 466 567 467 568 //! The existing instance of type T is initialized with values stored in the Setting element[name] 468 //! If there is not any sub-element named #name, this method returns false.569 //! If there does not exist any sub-element named #name, this method returns false. 469 570 template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 470 571 if ( !element.exists ( name ) ) { … … 480 581 481 582 //! The existing instance of type T is initialized with values stored in the Setting element[index] 482 //! If there is not any sub-element indexed by #index, this method returns false.583 //! If there does not exist any sub-element indexed by #index, this method returns false. 483 584 template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) { 484 585 if ( element.getLength() <= index ) { … … 551 652 //! or by its integer index. In that case, the new element is added at the very end of the current list of child Settings. 552 653 553 //! A root descendant instance is stored in the new child Setting appended to the passed element 554 template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) { 555 Setting &set = ( name == "" ) ? (element.getType()==Setting::TypeArray || element.getType()==Setting::TypeList) ? element.add ( Setting::TypeGroup ) : element 556 : element.add ( name, Setting::TypeGroup ); 557 558 const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) ); 559 560 // add attribute "class" 561 Setting &type = set.add ( "class", Setting::TypeString ); 562 type = class_name; 563 564 try { 565 instance->to_setting ( set ); 566 } catch ( SettingException &sttng_xcptn ) { 567 string msg = "UIException: method "; 568 msg += class_name; 569 msg += ".to_setting(Setting&) has thrown a SettingException."; 570 throw UISettingException ( msg, sttng_xcptn.getPath() ); 571 } 572 } 573 654 //! A root descendant is stored in the new child Setting appended to the passed element 655 static void save ( const root &instance, Setting &element, const string &name = "" ); 656 657 //! A pointer to root descendant is stored in the new child Setting appended to the passed element 658 static void save ( const root * const instance, Setting &element, const string &name = "" ); 659 660 //! A shared pointer to root descendant is stored in the new child Setting appended to the passed element 574 661 template< class T> static void save ( const bdm::shared_ptr<T> &instance, Setting &element, const string &name = "" ) { 575 save <T>( instance.get(), element, name );662 save( instance.get(), element, name ); 576 663 } 577 664 … … 603 690 static void save ( const double &real, Setting &element, const string &name = "" ); 604 691 605 // The only difference from classical UserInfo approach to log_level_template is the fact 606 // that the actual UI element related to log_level_template could possibly exists yet. In this case, 607 // we do not want to throw an exception like in the case of any other type being loaded 608 // from Setting. We rather fill the current log_level into this existig element. This way, it is 609 // possible that more instances of log_level_template class (templated with different classes) 692 // The only difference from classical UserInfo approach here is the fact 693 // that the actual UI element related to log_level_base could possibly exists yet. In this case, 694 // we do not want to throw an exception as usually. We rather append current data into the existig element. This way, it is 695 // possible that more instances of log_level_base (templated with different classes) 610 696 // can be stored in only one line in a configuration file 611 static void save ( const log_level_base &log_level, Setting &element, const string &name = "log_level" ); 697 template<class T> static void save ( const log_level_base<T> &log_level, Setting &element ) { 698 assert_type ( element, Setting::TypeGroup ); 699 string name = "log_level"; 700 701 if( element.exists( name ) ) 702 assert_type ( element[name], Setting::TypeString ); 703 else 704 element.add ( name, Setting::TypeString ); 705 706 log_level.to_setting( element[name] ); 707 } 612 708 613 709 //!@}