Show
Ignore:
Timestamp:
08/05/09 00:01:58 (15 years ago)
Author:
mido
Message:

1) ad UserInfo?: UI::get a UI::build predelany tak, ze vraci fals / NULL v pripade neexistence pozadovaneho Settingu, pridana enumericky typ UI::SettingPresence?, predelany stavajici UI implementace, dodelana UI dokumentace
2) dokoncena konfigurace ASTYLERU, brzy bude aplikovan
3) doxygen nastaven tak, ze vytvari soubor doxy_warnings.txt

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • library/bdm/base/user_info.h

    r417 r471  
    11/*! 
    22  \file 
    3   \brief UI (user info) class for loading/saving objects from/to configuration files.   
     3  \brief UI (user info) class for loading/saving objects from/to configuration files. 
    44  It is designed with use of libconfig C/C++ Configuration File Library 
     5  \ref ui_page 
    56  \author Vaclav Smidl. 
    67 
     
    3031using namespace libconfig; 
    3132 
    32 namespace bdm 
    33 { 
    34          
    35 /*! 
    36   \def UIREGISTER(class_name) 
    37   \brief Macro for registration of class into map of user-infos, registered class is scriptable using UI static methods 
    38    
    39   Argument \a class_name has to be a descendant of root class and also, it has to have parameterless constructor prepared. 
    40   This macro should be used in header file, immediately after a class declaration. 
    41    
    42   \sa TODO MODUL   
    43 */ 
    44 #ifndef BDMLIB  
    45         #define UIREGISTER(class_name) template<> const ParticularUI<class_name>& ParticularUI<class_name>::factory = ParticularUI<class_name>(#class_name)  
    46 #else 
    47         #define UIREGISTER(class_name) 
    48 #endif 
     33namespace bdm { 
    4934 
    5035//! Exception prepared for reporting user-info errors which are always related to some concrete Setting path 
    51 class UIException : public std::exception 
    52 { 
    53 private: 
     36//! 
     37//!  \ref ui_page 
     38class UIException : public std::exception { 
     39 
     40public: 
    5441        //! Error message 
    5542        const string message; 
    5643 
    57 public: 
     44        //! Path to the problematic setting 
     45        const string path; 
     46 
    5847        //! Use this constructor when you can pass the problematical Setting as a parameter 
    59         UIException( const string &message, const Setting &element  )  
    60                 : message( "UI error: " + message + ". Check path \"" + string(element.getPath()) + "\"." ) 
    61         { 
     48        UIException ( const string &message, const Setting &element ) 
     49                        : message ( "UI error: " + message + "." ), path ( "Check path \"" + string ( element.getPath() ) + "\"." ) { 
    6250        } 
    6351 
    6452        //! This constructor is for other occasions, when only path of problematical Setting is known 
    65         UIException( const string &message, const string &path  )  
    66                 : message( "UI error: " + message + "! Check path \"" + path + "\"." ) 
    67         { 
     53        UIException ( const string &message, const string &path ) 
     54                        : message ( "UI error: " + message + "." ), path ( "Check path \"" + path + "\"." ) { 
    6855        } 
    6956 
    7057        //! Overriden method for reporting an error message 
    71         virtual const char* what() const throw() 
    72         { 
    73                 return message.c_str(); 
     58        virtual const char* what() const throw() { 
     59                return ( message + " " + path ).c_str(); 
    7460        } 
    7561        ~UIException() throw() {}; 
     
    7864 
    7965/*! 
    80 @brief This class serves to load and/or save user-infos into/from  
     66@brief This class serves to load and/or save user-infos into/from 
    8167configuration files stored on a hard-disk. 
    8268 
    83 Firstly, save some user-infos into the new UIFile instance. Then,  
     69Firstly, save some user-infos into the new UIFile instance. Then, 
    8470call the save method with a filename as its only argument: 
    8571 
     
    9177\endcode 
    9278 
    93 In the other way round, when loading object from a configuration file,  
     79In the other way round, when loading object from a configuration file, 
    9480the appropriate code looks like this: 
    9581 
     
    9884        CAudi *audi = UI::build<CAudi>(file,"TT"); 
    9985\endcode 
     86 
     87\ref ui_page 
    10088*/ 
    101 class UIFile : public Config 
    102 { 
     89class UIFile : public Config { 
    10390public: 
    10491        //! Create empty file instance prepared to store Settings 
     
    10693 
    10794        //! Creates instance and fills it from the configuration file file_name 
    108         UIFile( const string &file_name ); 
     95        UIFile ( const string &file_name ); 
    10996 
    11097        //! Save all the stored Settings into the configuration file file_name 
    111         void save(const string &file_name); 
     98        void save ( const string &file_name ); 
    11299 
    113100        //! This operator allows the ability of substituting Setting parameter by UIFile instance 
     
    116103 
    117104/*! 
    118 @brief This class serves to expand links used within configuration files.  
     105@brief This class serves to expand links used within configuration files. 
    119106 
    120107Value of any type but string can be linked to some other value of the same type 
    121108defined elsewhere in the current configuration file or even in some different 
    122 configuration file.  
    123  
    124 Link have three parts, \<name\> : \<path\> \<\@filename\>. Field \<name\> contains the  
     109configuration file. 
     110 
     111Link have three parts, \<name\> : \<path\> \<\@filename\>. Field \<name\> contains the 
    125112name of the new setting, \<path\> is the relative path to the referenced setting, which 
    126 has to be taken from the %root Setting element. The last part \<\@filename\> is optional,  
     113has to be taken from the %root Setting element. The last part \<\@filename\> is optional, 
    127114it contains filename in the case the link should refer to a variable stored in a different 
    128115file. From the previous part \<path\>, it has to be separated by '@'. 
     
    130117\code 
    131118    ... 
    132         jardovo :  
     119        jardovo : 
    133120        { 
    134121          class = "Car"; 
     
    137124          kilometers = 1555000; 
    138125        }; 
    139         ondrejovo :  
     126        ondrejovo : 
    140127        { 
    141128          class = "Bike"; 
     
    145132          matr = ( 2, 2, [ 1.0, 0.0, 0.0, 1.0 ] ); 
    146133        }; 
    147          
    148         #this is the example of local link to another mean of transport  
     134 
     135        #this is the example of local link to another mean of transport 
    149136        elisky = "jardovo"; 
    150137 
    151138        ... 
    152139 
    153         # and this link is external link pointing to file "other_cars.cfg" stored in the 
    154         # same directory, in that file, it refers to the local Setting "magic_cars.skubankovo" 
     140        # And this link is external link pointing to the file "other_cars.cfg" stored in the 
     141        # same directory. In that file, it refers to the local Setting "magic_cars.skubankovo". 
    155142        kati = "magic_cars.skubankovo@other_cars.cfg"; 
    156143 
     
    172159\endcode 
    173160 
    174 The whole point is that a resolved link (class member #result, i.e., "link.result" in the previous example) could point  
     161The whole point is that a resolved link (class member #result, i.e., "link.result" in the previous example) could point 
    175162into a different configuration file. In that case there has to be an UIFile instance managing reading from this 
    176 file. As the libconfig::Config deletes all its Settings when dealocated, UIFile must not be dealocated until all  
    177 the necessary operation on the linked Setting are finished (otherwise, the link #result would be invalid just after  
    178 the UIFile dealocation). And that is exactly the mechanism implemented within SettingResolver class. It assures,  
     163file. As the libconfig::Config deletes all its Settings when dealocated, UIFile must not be dealocated until all 
     164the necessary operation on the linked Setting are finished (otherwise, the link #result would be invalid just after 
     165the UIFile dealocation). And that is exactly the mechanism implemented within SettingResolver class. It assures, 
    179166that the #result Setting reference is valid within the scope of SettingResolver instance. 
     167         
     168\ref ui_page 
    180169 */ 
    181 class SettingResolver : root 
    182 { 
     170class SettingResolver : root { 
    183171private: 
    184172        //! If necessary, this pointer stores an addres of an opened UIFile, else it equals NULL 
     
    187175        //! This method initialize #result reference, i.e., it executes the main code of SettingResolver class 
    188176        //! 
    189         //! This code could be also located directly in constructor. The only reason why we made this  
     177        //! This code could be also located directly in constructor. The only reason why we made this 
    190178        //! method is the keyword 'const' within the declaration of #result reference . Such a reference 
    191179        //! have to be intialized before any other constructor command, exactly in the way it is implemented now. 
    192         const Setting &initialize_reference( UIFile* &file, const Setting &potential_link); 
     180        const Setting &initialize_reference ( UIFile* &file, const Setting &potential_link ); 
    193181 
    194182public: 
     
    197185 
    198186        //! If potential_link contains a link to some other setting, it is resolved here. Anyway, the Setting reference #result is prepared for use. 
    199         SettingResolver( const Setting &potential_link ); 
    200          
     187        SettingResolver ( const Setting &potential_link ); 
     188 
    201189        //! An opened UIFile file is closed here if necessary. 
    202         ~SettingResolver();              
     190        ~SettingResolver(); 
    203191}; 
    204192 
    205193/*! 
    206 @brief UI is an abstract class and it is intended for internal purposes only 
    207  
    208 This class exists mainly to allow pointers to its templated descendant ParticularUI<T>. Next,  
    209 it collects all the auxiliary functions useful to prepare some concret user-infos, see static  
    210 methods 'build', 'get' and 'save'.  
     194@brief UI is an abstract class which collects all the auxiliary functions useful to prepare some concrete 
     195user-infos. 
     196 
     197See static methods 'build', 'get' and 'save'. Writing user-infos with these methods is rather  simple. The 
     198rest of this class is intended for internal purposes only. Its meaning is to allow pointers to its templated 
     199descendant ParticularUI<T>. 
     200 
     201\ref ui_page 
    211202*/ 
    212 class UI  
    213 { 
     203class UI { 
    214204private: 
    215205        //! Class with state shared across all its instances ("monostate"), encapsulating two maps, one mapping names to UI instances and the other mapping type_infos to class names 
    216         //!  
     206        //! 
    217207        //! The key property of this class is that it initializes the internal maps on global init, 
    218         //! before the instance is used for a first time. Therefore, we do not have to care about initialization  
     208        //! before the instance is used for a first time. Therefore, we do not have to care about initialization 
    219209        //! during a call of UIREGISTER macro operating with both these mappings. 
    220         class MappedUI 
    221         { 
     210        class MappedUI { 
    222211        private: 
    223212                //! Type definition of mapping which transforms class names to the related UI instances 
     
    234223 
    235224                //! Method for reporting a error when an attempt to operate with an unregistered class occures 
    236                 static void unregistered_class_error( const string &unregistered_class_name ); 
     225                static void unregistered_class_error ( const string &unregistered_class_name ); 
    237226 
    238227        public: 
    239228                //! Add a pair key-userinfo into the internal map 
    240                 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui ); 
     229                static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui ); 
    241230 
    242231                //! Search for an userinfo related to the passed class name within the internal map 
    243                 static const UI& retrieve_ui( const string &class_name ); 
     232                static const UI& retrieve_ui ( const string &class_name ); 
    244233 
    245234                //! Search for an class name related to the passed type_info within the internal map 
    246                 static const string& retrieve_class_name( const type_info* const class_type_info ); 
     235                static const string& retrieve_class_name ( const type_info* const class_type_info ); 
    247236        }; 
    248237 
    249238        //! Function assertting that the setting element is of the SettingType type 
    250         static void assert_type( const Setting &element, Setting::Type type); 
     239        static void assert_type ( const Setting &element, Setting::Type type ); 
    251240 
    252241        //! Method assembling a typeless instance, it is implemented in descendant class ParticularUI<T> 
    253242        virtual root* new_instance() const = 0; 
    254          
    255         //! Method switching from the \a element to its child Setting according the passed \a index, it also does all the necessary error-checking  
    256         static const Setting& to_child_setting( const Setting &element, const int index ); 
    257  
    258         //! Method switching from the \a element to its child Setting according the passed \a name, it also does all the necessary error-checking  
    259         static const Setting& to_child_setting( const Setting &element, const string &name ); 
    260  
    261         //! This method converts a Setting into a matrix  
    262         static void from_setting( mat& matrix, const Setting &element );         
     243 
     244        //! Method switching from the \a element to its child Setting according the passed \a index, it also does all the necessary error-checking 
     245        static const Setting& to_child_setting ( const Setting &element, const int index ); 
     246 
     247        //! Method switching from the \a element to its child Setting according the passed \a name, it also does all the necessary error-checking 
     248        static const Setting& to_child_setting ( const Setting &element, const string &name ); 
     249 
     250        //! This method converts a Setting into a matrix 
     251        static void from_setting ( mat& matrix, const Setting &element ); 
    263252        //! This method converts a Setting into an integer vector 
    264         static void from_setting( ivec &vector, const Setting &element ); 
     253        static void from_setting ( ivec &vector, const Setting &element ); 
    265254        //! This method converts a Setting into a string 
    266         static void from_setting( string &str, const Setting &element ); 
     255        static void from_setting ( string &str, const Setting &element ); 
    267256        //! This method converts a Setting into a real vector 
    268         static void from_setting( vec &vector, const Setting &element ); 
    269         //! This method converts a Setting into a integer scalar  
    270         static void from_setting( int &integer, const Setting &element ); 
    271         //! This method converts a Setting into a real scalar  
    272         static void from_setting( double &real, const Setting &element ); 
     257        static void from_setting ( vec &vector, const Setting &element ); 
     258        //! This method converts a Setting into a integer scalar 
     259        static void from_setting ( int &integer, const Setting &element ); 
     260        //! This method converts a Setting into a real scalar 
     261        static void from_setting ( double &real, const Setting &element ); 
    273262        //! This method converts a Setting into a class T descendant 
    274         template<class T> static void from_setting( T* &instance, const Setting &element ) 
    275         {                        
    276                 const SettingResolver link( element ); 
    277                 assert_type(link.result,Setting::TypeGroup); 
    278  
    279                 // we get a value stored in the "class" attribute  
     263        template<class T> static void from_setting ( T* &instance, const Setting &element ) { 
     264                const SettingResolver link ( element ); 
     265                assert_type ( link.result, Setting::TypeGroup ); 
     266 
     267                // we get a value stored in the "class" attribute 
    280268                string class_name; 
    281                 if( !link.result.lookupValue( "class", class_name ) ) 
    282                         throw UIException( "the obligatory \"class\" identifier is missing", link.result ); 
    283          
     269                if ( !link.result.lookupValue ( "class", class_name ) ) 
     270                        throw UIException ( "the obligatory \"class\" identifier is missing", link.result ); 
     271 
    284272                // then we find a user-info related to this type 
    285                 const UI& related_UI = MappedUI::retrieve_ui( class_name ); 
    286                  
     273                const UI& related_UI = MappedUI::retrieve_ui ( class_name ); 
     274 
    287275                root* typeless_instance = related_UI.new_instance(); 
    288276 
    289                 instance = dynamic_cast<T*>(typeless_instance); 
    290                 if (!instance) 
    291                         throw UIException( "class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build<T> function with a different type parameter.", link.result ); 
    292                  
    293                 try 
    294                 { 
    295                         instance->from_setting( link.result ); 
     277                instance = dynamic_cast<T*> ( typeless_instance ); 
     278                if ( !instance ) 
     279                        throw UIException ( "class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build<T> function with a different type parameter.", link.result ); 
     280 
     281                try { 
     282                        instance->from_setting ( link.result ); 
     283                } catch ( SettingException sttng_xcptn ) { 
     284                        string msg = "the method " + class_name + ".from_setting(Setting&) has thrown a SettingException. Try to correct this method. Check path \"" + sttng_xcptn.getPath() + "\"."; 
     285                        throw exception ( msg.c_str() ); 
     286                } catch ( UIException uixcptn ) { 
     287                        string msg = "the method " + class_name + ".from_setting(Setting&) has thrown an UIException \"" + uixcptn.message + "\" Try to correct this method. Check path \"" + uixcptn.path + "\"."; 
     288                        throw exception ( msg.c_str() ); 
     289                } catch ( exception xcptn ) { 
     290                        string msg = "the method " + class_name + ".from_setting(Setting&) has thrown a general exception \"" + xcptn.what() + "\" Try to correct this method. Check path \"" + element.getPath() + "\"."; 
     291                        throw exception ( msg.c_str() ); 
    296292                } 
    297                 catch(SettingException xcptn) 
    298                 { 
    299                         throw UIException( "the method " + class_name + ".from_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath()); 
    300                 } 
    301         }        
     293        } 
    302294 
    303295        //! This methods converts a Setting into a new templated array of type Array<T> 
    304         template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element ) 
    305         { 
    306                 const SettingResolver link( element ); 
    307  
    308                 assert_type(link.result,Setting::TypeList); 
     296        template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) { 
     297                const SettingResolver link ( element ); 
     298 
     299                assert_type ( link.result, Setting::TypeList ); 
    309300 
    310301                int len = link.result.getLength(); 
    311                 array_to_load.set_length( len ); 
    312                 if( len == 0 ) return; 
    313                  
    314                 for( int i=0; i < len; i++ )  
    315                         from_setting( array_to_load(i), link.result[i] );  
    316         } 
     302                array_to_load.set_length ( len ); 
     303                if ( len == 0 ) return; 
     304 
     305                for ( int i = 0; i < len; i++ ) 
     306                        from_setting ( array_to_load ( i ), link.result[i] ); 
     307        } 
     308 
     309        //! This is dummy version of the from_setting method for other, unsupported types. It just throws an exception. 
     310        //! 
     311        //! At the moment, this is the only way how to compile the library without obtaining the compiler error c2665. 
     312        //! The exception can help to find the place where the template is misused and also to correct it. 
     313        template<class T> static void from_setting ( T &array_to_load, const Setting &element ) { 
     314                throw UIException( "from_setting is not implemented for this type", element ); 
     315        } 
     316 
    317317 
    318318protected: 
    319319        //! Default constructor for internal use only, see \sa ParticularUI<T> 
    320         UI( const string& class_name, const type_info * const class_type_info )  
    321         {        
    322                 MappedUI::add_class( class_name, class_type_info, this ); 
    323         } 
    324  
    325 public:  
    326  
    327         //! \name Initialization of classes  
     320        UI ( const string& class_name, const type_info * const class_type_info ) { 
     321                MappedUI::add_class ( class_name, class_type_info, this ); 
     322        } 
     323 
     324public: 
     325 
     326        //! Enumerical type used to determine whether the data for concrete Settingis is compulsory or optional  
     327        enum SettingPresence { optional, compulsory } ; 
     328 
     329        //! \name Initialization of classes 
    328330        //!@{ 
    329         //! The type T has to be a root descendant class 
     331        //! The type T has to be a #bdm::root descendant class 
    330332 
    331333        //! The new instance of type T* is constructed and initialized with values stored in the Setting element[name] 
    332         template<class T> static T* build( const Setting &element, const string &name ) 
    333         {                        
     334        //! 
     335        //! If there is not any sub-element named #name, the null pointer is returned. 
     336        template<class T> static T* build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 
     337                if ( !element.exists ( name ) ) 
     338                { 
     339                        if( settingPresence == optional ) 
     340                                return NULL; 
     341                        else 
     342                                throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element ); 
     343                } 
     344 
    334345                T* instance; 
    335                 from_setting<T>( instance, to_child_setting( element, name ) ); 
     346                from_setting<T> ( instance, to_child_setting ( element, name ) ); 
    336347                return instance; 
    337348        } 
     349 
    338350        //! The new instance of type T* is constructed and initialized with values stored in the Setting element[index] 
    339         template<class T> static T* build( const Setting &element, const int index ) 
    340         { 
     351        //! 
     352        //! If there is not any sub-element indexed by #index, the null pointer is returned. 
     353        template<class T> static T* build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) { 
     354                if ( element.getLength() <= index ) 
     355                { 
     356                        if( settingPresence == optional ) 
     357                                return NULL; 
     358                        else 
     359                        { 
     360                                stringstream stream; 
     361                                stream << index; 
     362                                throw UIException ( "the compulsory Setting with the index " + stream.str()+ " is missing", element ); 
     363                        } 
     364                } 
     365 
    341366                T* instance; 
    342                 from_setting<T>( instance, to_child_setting( element, index ) ); 
     367                from_setting<T> ( instance, to_child_setting ( element, index ) ); 
    343368                return instance; 
    344369        } 
     370 
    345371        //! The new instance of type T* is constructed and initialized with values stored in the Setting element 
    346         template<class T> static T* build( const Setting &element ) 
    347         { 
     372        template<class T> static T* build ( const Setting &element ) { 
    348373                T* instance; 
    349                 from_setting<T>( instance,  element ); 
     374                from_setting<T> ( instance,  element ); 
    350375                return instance; 
    351         } 
     376 
     377        } 
     378 
    352379        //!@} 
    353380 
    354         //! \name Initialization of structures  
     381        //! \name Initialization of structures 
    355382        //!@{ 
    356383        //! The type T has to be int, double, string, vec, ivec or mat. 
    357384 
    358385        //! The existing instance of type T is initialized with values stored in the Setting element[name] 
    359         template<class T> static void get( T &instance, const Setting &element, const string &name ) 
    360         { 
    361                 from_setting( instance, to_child_setting( element, name ) ); 
    362         } 
    363  
    364         //! The existing instance of type T is initialized with values stored in the Setting element[index]  
    365         template<class T> static void get( T &instance, const Setting &element, const int index ) 
    366         { 
    367                 from_setting( instance, to_child_setting( element, index ) ); 
     386        //! If there is not any sub-element named #name, this method returns false. 
     387        template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 
     388                if ( !element.exists ( name ) ) 
     389                { 
     390                        if( settingPresence == optional ) 
     391                                return false; 
     392                        else 
     393                                throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element ); 
     394                } 
     395 
     396                from_setting ( instance, to_child_setting ( element, name ) ); 
     397                return true; 
     398        } 
     399 
     400        //! The existing instance of type T is initialized with values stored in the Setting element[index] 
     401        //! If there is not any sub-element indexed by #index, this method returns false. 
     402        template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) { 
     403                if ( element.getLength() <= index ) 
     404                { 
     405                        if( settingPresence == optional ) 
     406                                return false; 
     407                        else 
     408                        { 
     409                                stringstream stream; 
     410                                stream << index; 
     411                                throw UIException ( "the compulsory Setting with the index " + stream.str()+ " is missing", element ); 
     412                        } 
     413                } 
     414 
     415                from_setting ( instance, to_child_setting ( element, index ) ); 
     416                return true; 
    368417        } 
    369418 
    370419        //! The existing instance of type T is initialized with values stored in the Setting element directly 
    371         template<class T> static void get( T &instance, const Setting &element  ) 
    372         { 
    373                 from_setting( instance, element ); 
     420        template<class T> static bool get ( T &instance, const Setting &element ) { 
     421                from_setting ( instance, element ); 
     422                return true; 
    374423        } 
    375424        //!@} 
     
    380429 
    381430        //! The existing array of type T is initialized with values stored in the Setting element[name] 
    382         template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name ) 
    383         { 
    384                 from_setting( array_to_load, to_child_setting( element, name ) ); 
     431        //! If there is not any sub-element named #name, this method returns false. 
     432        template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 
     433                if ( !element.exists ( name ) ) 
     434                        return false; 
     435 
     436                from_setting ( array_to_load, to_child_setting ( element, name ) ); 
     437                return true; 
    385438        } 
    386439 
    387440        //! The existing array of type T is initialized with values stored in the Setting element[index] 
    388         template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index ) 
    389         { 
    390                 from_setting( array_to_load, to_child_setting( element, index ) ); 
     441        //! If there is not any sub-element indexed by #index, this method returns false. 
     442        template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) { 
     443                if ( element.getLength() <= index ) 
     444                        return false; 
     445 
     446                from_setting ( array_to_load, to_child_setting ( element, index ) ); 
     447                return true; 
    391448        } 
    392449 
    393450        //! The existing array of type T is initialized with values stored in the Setting element 
    394         template<class T> static void get( Array<T> &array_to_load, const Setting &element  ) 
    395         { 
    396                 from_setting( array_to_load, element ); 
     451        template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) { 
     452                from_setting ( array_to_load, element ); 
     453                return true; 
    397454        } 
    398455        //!@} 
    399456 
    400         //! \name Serialization of objects and structures into a new Setting  
     457        //! \name Serialization of objects and structures into a new Setting 
    401458        //!@{ 
    402459        //! The new child Setting can be accessed either by its name - if some name is passed as a parameter - 
     
    404461 
    405462        //! A root descendant instance is stored in the new child Setting appended to the passed element 
    406         template< class T> static void save( const T * const instance, Setting &element, const string &name = "") 
    407         { 
    408                 Setting &set = (name == "") ? element.add( Setting::TypeGroup )                                                  
    409                                                                          : element.add( name, Setting::TypeGroup );              
    410  
    411                 const string &class_name = MappedUI::retrieve_class_name( &typeid(*instance) ); 
    412                          
    413                 // add attribute "class"  
    414                 Setting &type = set.add( "class", Setting::TypeString ); 
     463        template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) { 
     464                Setting &set = ( name == "" ) ? element.add ( Setting::TypeGroup ) 
     465                               : element.add ( name, Setting::TypeGroup ); 
     466 
     467                const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) ); 
     468 
     469                // add attribute "class" 
     470                Setting &type = set.add ( "class", Setting::TypeString ); 
    415471                type = class_name; 
    416472 
    417                 try 
    418                 { 
    419                         instance->to_setting( set ); 
     473                try { 
     474                        instance->to_setting ( set ); 
     475                } catch ( SettingException sttng_xcptn ) { 
     476                        string msg = "the method " + class_name + ".to_setting(Setting&) has thrown a SettingException. Try to correct this method. Check path \"" + sttng_xcptn.getPath() + "\"."; 
     477                        throw exception ( msg.c_str() ); 
     478                } catch ( UIException uixcptn ) { 
     479                        string msg = "the method " + class_name + ".to_setting(Setting&) has thrown an UIException \"" + uixcptn.message + "\" Try to correct this method. Check path \"" + uixcptn.path + "\"."; 
     480                        throw exception ( msg.c_str() ); 
     481                } catch ( exception xcptn ) { 
     482                        string msg = "the method " + class_name + ".to_setting(Setting&) has thrown a general exception \"" + xcptn.what() + "\" Try to correct this method. Check path \"" + element.getPath() + "\"."; 
     483                        throw exception ( msg.c_str() ); 
    420484                } 
    421                 catch(SettingException xcptn) 
    422                 { 
    423                         throw UIException( "the method " + class_name + ".to_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath()); 
    424                 }        
    425485        } 
    426486 
    427487        //! An Array<T> instance is stored in the new child Setting appended to the passed element 
    428         template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" ) 
    429         { 
    430                 assert_type(element,Setting::TypeGroup); 
    431                 Setting &list = (name == "") ? element.add( Setting::TypeList )                                                  
    432                                                                          : element.add( name, Setting::TypeList );               
    433                 for( int i=0; i<array_to_save.length(); i++ )  
    434                         save( array_to_save(i), list ); 
     488        template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) { 
     489                assert_type ( element, Setting::TypeGroup ); 
     490                Setting &list = ( name == "" ) ? element.add ( Setting::TypeList ) 
     491                                : element.add ( name, Setting::TypeList ); 
     492                for ( int i = 0; i < array_to_save.length(); i++ ) 
     493                        save ( array_to_save ( i ), list ); 
    435494        } 
    436495 
    437496        //! A matrix(of type mat) is stored in the new child Setting appended to the passed element 
    438         static void save( const mat &matrix, Setting &element, const string &name = "" ); 
     497        static void save ( const mat &matrix, Setting &element, const string &name = "" ); 
    439498 
    440499        //! An integer vector (of type ivec) is stored in the new child Setting appended to the passed element 
    441         static void save( const ivec &vec, Setting &element, const string &name = "" ); 
    442          
     500        static void save ( const ivec &vec, Setting &element, const string &name = "" ); 
     501 
    443502        //! A double vector (of type vec) is stored in the new child Setting appended to the passed element 
    444         static void save( const vec &vector, Setting &element, const string &name = "" ); 
     503        static void save ( const vec &vector, Setting &element, const string &name = "" ); 
    445504 
    446505        //! A string is stored in the new child Setting appended to the passed element 
    447         static void save( const string &str, Setting &element, const string &name = "" ); 
     506        static void save ( const string &str, Setting &element, const string &name = "" ); 
    448507 
    449508        //! An integer is stored in the new child Setting appended to the passed element 
    450         static void save( const int &integer, Setting &element, const string &name = "" ); 
     509        static void save ( const int &integer, Setting &element, const string &name = "" ); 
    451510 
    452511        //! A double is stored in the new child Setting appended to the passed element 
    453         static void save( const double &real, Setting &element, const string &name = "" );       
     512        static void save ( const double &real, Setting &element, const string &name = "" ); 
    454513        //!@} 
    455514 
     
    458517 
    459518//! The only UI descendant class which is not intended for direct use. It should be accessed within the ::UIREGISTER macro only. 
    460 template<typename T> class ParticularUI : private UI 
    461 { 
     519//! \ref ui_page 
     520template<typename T> class ParticularUI : private UI { 
    462521private: 
    463522        //! Default constructor, which is intentionally declared as private 
    464         ParticularUI<T>( const string &class_name) : UI( class_name, &typeid(T) )  
    465         {}; 
     523        ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {}; 
    466524 
    467525public: 
    468526        //! The only instance of this class (each type T has its own instance) which is used as a factory for processing related UI 
    469         static const ParticularUI<T>& factory;   
     527        static const ParticularUI<T>& factory; 
    470528 
    471529        //! A method returning a brand new instance of class T, this method is the reason why there have to be a parameterless construcotor in class T 
    472         root* new_instance() const 
    473         { 
     530        root* new_instance() const { 
    474531                return new T(); 
    475532        } 
     
    478535} 
    479536 
     537/*! 
     538  \def UIREGISTER(class_name) 
     539  \brief Macro for registration of class into map of user-infos, registered class is scriptable using UI static methods 
     540 
     541  Argument \a class_name has to be a descendant of root class and also, it has to have parameterless constructor prepared. 
     542  This macro should be used in header file, immediately after a class declaration. 
     543 
     544  \ref ui_page 
     545*/ 
     546#ifndef BDMLIB 
     547#define UIREGISTER(class_name) template<> const ParticularUI<class_name>& ParticularUI<class_name>::factory = ParticularUI<class_name>(#class_name) 
     548#else 
     549#define UIREGISTER(class_name) 
     550#endif 
     551 
    480552#endif // #ifndef USER_INFO_H