- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

# userinfo.h

    00001 #ifndef UI_H
    00002 #define UI_H
    00003
    00004 #include <sstream>
    00005 #include <iostream>
    00006 #include <stdio.h>
    00007 #include <string>
    00008 #include <typeinfo>
    00009 #include <map>
    00010 #include <utility>
    00011 #include <vector>
    00012 #include <xercesc/dom/DOM.hpp>
    00013 #include <xercesc/util/PlatformUtils.hpp>
    00014 #include <xercesc/util/XMLString.hpp>
    00015 #include <iostream>
    00016 #include <xercesc/framework/LocalFileFormatTarget.hpp>
    00017 #include <xercesc/framework/LocalFileInputSource.hpp>
    00018 #include <xercesc/dom/DOMWriter.hpp>
    00019 #include <xercesc/parsers/XercesDOMParser.hpp>
    00020
    00021 #ifdef XERCES_CPP_NAMESPACE_USE
    00022 XERCES_CPP_NAMESPACE_USE
    00023 #endif
    00024
    00025 using std::string;
    00026 using namespace std;
    00027
    00040 class AssertXercesIsAlive
    00041 {
    00042 private:
    00044         class XercesConnector
    00045         {
    00046         private:
    00049                 XercesConnector()
    00050                 {
    00051                         // initialize the XML library
    00052                         XMLPlatformUtils::Initialize();
    00053                 }
    00054
    00055                 ~XercesConnector()
    00056                 {
    00057                         // terminate the XML library
    00058                         XMLPlatformUtils::Terminate();
    00059                 }
    00060
    00061         public:
    00068                 static void StayAlive()
    00069                 {
    00070                         static XercesConnector xc;
    00071                 };
    00072         };
    00073
    00074
    00075 public:
    00077         AssertXercesIsAlive()
    00078         {
    00079                 XercesConnector::StayAlive();
    00080         }
    00081 };
    00082
    00086 class BindingFrame
    00087 {
    00088 private:
    00092         AssertXercesIsAlive dummy;
    00093
    00094 protected:
    00096         BindingFrame();
    00097
    00099         string XMLCh2str( const XMLCh* const  XMLCh_str );
    00100
    00101         string removeSpaces(const string &str)
    00102         {
    00103                 std::string temp;
    00104                 for (unsigned int i = 0; i < str.length(); i++)
    00105                         if (str[i] == ' ') temp += '_';
    00106                         else temp += str[i];
    00107                 return temp;
    00108         }
    00109
    00110 public:
    00112         virtual void AssemblyComponentsFromXML( DOMElement &element ) = 0;
    00113
    00115         virtual void ReleaseMemory() {}
    00116
    00119         virtual bool DisassemblyComponentsToXML( DOMElement &element ) = 0;
    00120 };
    00121
    00125 class Attribute
    00126 {
    00127 private:
    00131         AssertXercesIsAlive dummy;
    00132
    00134         const XMLCh* const transcodedAttributeName;
    00135
    00136 public:
    00138         Attribute( string attributeName );
    00139
    00140         ~Attribute();
    00141
    00143         string& Get( DOMElement &element ) const;
    00144
    00146         void Set( DOMElement &element, const string &str ) const;
    00147
    00149         static const Attribute help;
    00150
    00152         static const Attribute type;
    00153
    00155         static const Attribute value;
    00156 };
    00157
    00158
    00159
    00167 class UserInfo : protected BindingFrame
    00168 {
    00169 private:
    00171         typedef UserInfo* const pUserInfo;
    00172
    00177         class StringToUIMap
    00178         {
    00179         private:
    00181                 typedef map< const string, pUserInfo > MappedString2UI;
    00182
    00184                 static MappedString2UI& privateMap();
    00185
    00186         public:
    00188                 static void Add( string key, pUserInfo pInstance );
    00189
    00191                 static pUserInfo Retrieve( string key );
    00192         };
    00193
    00195         virtual void* AssemblyTypelessInstance() = 0;
    00196
    00198         virtual bool DisassemblyTypelessInstance(void* pInstance) = 0;
    00199
    00201         const string userFriendlyTypeName;
    00202
    00204         const string typeNameByRTTI;
    00205
    00206 protected:
    00207
    00209         UserInfo( const string& userFriendlyTypeName, const string& typeNameByRTTI )
    00210                 : userFriendlyTypeName ( removeSpaces( userFriendlyTypeName ) ),
    00211                   typeNameByRTTI( typeNameByRTTI )
    00212         {
    00213                 StringToUIMap::Add( userFriendlyTypeName, this );
    00214
    00215                 if( userFriendlyTypeName != typeNameByRTTI )
    00216                         // we have a common map for both groups of names,
    00217                         // therefore, it is no use to add the same pair again
    00218                         StringToUIMap::Add( typeNameByRTTI, this );
    00219         }
    00220
    00221 public:
    00225         template<class T>
    00226         static T* Assembly( DOMElement &element, const string tagName )
    00227         {
    00228                 XMLCh* transcodedTagName = XMLString::transcode( tagName.c_str() );
    00229                 XMLString::upperCase( transcodedTagName );
    00230
    00231                 DOMNodeList* const nodeList = element.getElementsByTagName( transcodedTagName );
    00232                 XMLString::release( (XMLCh**)&transcodedTagName );
    00233                 if( !nodeList || nodeList->getLength() == 0 )
    00234                 {
    00235                         cerr << "Warning: there is not any tag named """ << tagName << """ in the passed DOM element of a XML docmument!";
    00236                         return NULL;
    00237                 }
    00238
    00239                 if( nodeList->getLength() > 1 )
    00240                 {
    00241                         cerr << "Warning: there is to many elements named """ << tagName << """ in the passed DOM element of a XML docmument. But the tag name has to be unique!";
    00242                         return NULL;
    00243                 }
    00244
    00245                 // this time we hold an element with the same name as the tagName is
    00246                 DOMElement* pTheOnlyElement = (DOMElement*) nodeList->item(0);
    00247
    00248                 // we get a velue stored in the "type" attribute
    00249                 string userFriendlyTypeName = Attribute::type.Get( *pTheOnlyElement );
    00250
    00251                 // and finally we find a UserInfo related to this type
    00252                 pUserInfo pRelatedUI = StringToUIMap::Retrieve( userFriendlyTypeName );
    00253                 if( !pRelatedUI )
    00254                 {
    00255                         cerr << "Warning: there is not any UserInfo related to type named """ << userFriendlyTypeName << """, instance assembling terminated!";
    00256                         return NULL;
    00257                 }
    00258
    00259                 // prepare all components necessary for an instance assembling
    00260                 pRelatedUI->AssemblyComponentsFromXML( *pTheOnlyElement );
    00261
    00262                 // instance assembling
    00263                 void* pTypelessInstance = pRelatedUI->AssemblyTypelessInstance();
    00264
    00265                 // cleaning up
    00266                 pRelatedUI->ReleaseMemory();
    00267
    00268                 if( pTypelessInstance == NULL )
    00269                 {
    00270                         cerr << "Warning: there was some error when parsing a XML document, instance assembling terminated!";
    00271                         return NULL;
    00272                 }
    00273
    00274                 T* pInstance = NULL;
    00275                 try
    00276                 {
    00277                         // a "do it yourself" type check:)
    00278                         pInstance = (T*) pTypelessInstance;
    00279                         string resultingTypeNameByRTTI = typeid( *pInstance ).name();
    00280                         if( resultingTypeNameByRTTI != pRelatedUI->typeNameByRTTI )
    00281                                 pInstance = NULL;
    00282                 }
    00283                 catch(...)
    00284                 {
    00285                         pInstance = NULL;
    00286                 }
    00287                 if( pInstance == NULL )
    00288                         cerr << "Warning: UserInfo related to type """ << userFriendlyTypeName << """ have just returned instance of a different type! Instance assembling terminated!";
    00289
    00290                 return pInstance;
    00291         }
    00292
    00296         template<class T>
    00297         static bool Disassembly( T& instance, DOMElement &element, const string tagName, const string help)
    00298         {
    00299                 pUserInfo pRelatedUI = StringToUIMap::Retrieve( typeid(instance).name() );
    00300                 if( !pRelatedUI )
    00301                         return false;
    00302
    00303                 // add a new element named according the passed tagName
    00304                 XMLCh* transcodedTagName = XMLString::transcode( tagName.c_str() );
    00305                 XMLString::upperCase( transcodedTagName );
    00306                 DOMDocument* pDoc = element.getOwnerDocument();
    00307                 DOMElement* pCreatedElement = pDoc->createElement( transcodedTagName );
    00308                 element.appendChild( pCreatedElement );
    00309                 XMLString::release( (XMLCh**)&transcodedTagName );
    00310
    00311                 // add attributes "type" and "help"
    00312                 Attribute::type.Set( *pCreatedElement, pRelatedUI->userFriendlyTypeName );
    00313                 Attribute::help.Set( *pCreatedElement, help );
    00314
    00315                 // disassembly instance itself into its components
    00316                 bool result =  pRelatedUI->DisassemblyTypelessInstance( (void*) &instance );
    00317                 if( result )
    00318                         // disassembly all components of an instance
    00319                         result = pRelatedUI->DisassemblyComponentsToXML( *pCreatedElement );
    00320                 return result;
    00321         }
    00322
    00326         template<class T>
    00327         static bool Disassembly( T &instance, DOMElement &element, const string tagName )
    00328         {
    00329                 return Disassembly( instance, element, tagName, "" );
    00330         }
    00331 };
    00332
    00344 template<typename T> class TypedUserInfo : public UserInfo
    00345 {
    00346 private:
    00347
    00348         bool DisassemblyTypelessInstance(void* pInstance)
    00349         {
    00350                 try
    00351                 {
    00352                         return DisassemblyInstance( *(T*) pInstance );
    00353                 }
    00354                 catch (...)
    00355                 {
    00356                         return false;
    00357                 }
    00358         }
    00359
    00360         void* AssemblyTypelessInstance()
    00361         {
    00362                 return (void*) AssemblyInstance( );
    00363         }
    00364
    00366         virtual T* AssemblyInstance() = 0;
    00367
    00369         virtual bool DisassemblyInstance(T& instance) = 0;
    00370
    00371 protected:
    00372
    00374         TypedUserInfo<T>( const string &userFriendlyTypeName)
    00375                 : UserInfo( userFriendlyTypeName, typeid(T).name() )
    00376         {
    00377
    00378         };
    00379
    00381         ~TypedUserInfo<T>()
    00382         {
    00383         }
    00384
    00387         static const TypedUserInfo<T>& instance;
    00388 };
    00389
    00390
    00420 template<typename T> class CompoundUserInfo : public TypedUserInfo<T>
    00421 {
    00422 private:
    00424         vector<BindingFrame*> bindedElements;
    00425
    00426 protected:
    00427
    00432         template<typename U> class BindedElement: public BindingFrame
    00433         {
    00434         private:
    00435                 string name;
    00436                 string help;
    00437                 bool release;
    00438
    00439                 U* pValue;
    00440
    00441                 const U defaultValue;
    00442
    00443
    00444         public:
    00445                 U value;
    00446
    00447                 BindedElement<U>( CompoundUserInfo<T> *parent, string name, U defaultValue, string help )
    00448                         : name( removeSpaces( name )), help(help), defaultValue( defaultValue )
    00449                 {
    00450                         parent->bindedElements.push_back( this );
    00451                         pValue = NULL;
    00452                         value = defaultValue;
    00453                 }
    00454
    00455                 BindedElement<U>( CompoundUserInfo<T> *parent, string name, U defaultValue )
    00456                         : name( removeSpaces( name )), help(""), defaultValue( defaultValue ), value( defaultValue)
    00457                 {
    00458                         parent->bindedElements.push_back( this );
    00459                         pValue = NULL;
    00460                         value = defaultValue;
    00461                 }
    00462
    00463                 ~BindedElement<U>()
    00464                 {
    00465                 }
    00466
    00467                 void AssemblyComponentsFromXML( DOMElement &element )
    00468                 {
    00469                         pValue = UserInfo::Assembly<U>( element, name );
    00470                         if( pValue ) value = *pValue;
    00471                 }
    00472
    00473                 void ReleaseMemory()
    00474                 {
    00475                         if( pValue != NULL )
    00476                                 delete pValue;
    00477                 }
    00478
    00479                 bool DisassemblyComponentsToXML( DOMElement &element )
    00480                 {
    00481                         return UserInfo::Disassembly( value, element, name, help );
    00482                 }
    00483         };
    00484
    00485 private:
    00486
    00487         void AssemblyComponentsFromXML( DOMElement &element )
    00488         {
    00489                 for( unsigned int ind = 0; ind < bindedElements.size(); ind++ )
    00490                         bindedElements[ind]->AssemblyComponentsFromXML( element );
    00491         }
    00492
    00493         void ReleaseMemory()
    00494         {
    00495                 for( unsigned int ind = 0; ind < bindedElements.size(); ind++ )
    00496                         bindedElements[ind]->ReleaseMemory();
    00497         }
    00498
    00499         bool DisassemblyComponentsToXML( DOMElement &element )
    00500         {
    00501                 for( unsigned int ind = 0; ind < bindedElements.size(); ind++ )
    00502                         if( !bindedElements[ind]->DisassemblyComponentsToXML( element ) )
    00503                                 return false;
    00504                 return true;
    00505         }
    00506
    00507 protected:
    00508
    00509         CompoundUserInfo<T>( string userFriendlyTypeName )
    00510                 : TypedUserInfo<T>( userFriendlyTypeName )
    00511         {
    00512         }
    00513
    00514 };
    00515
    00516
    00527 template<typename T> class ValuedUserInfo : public TypedUserInfo<T>
    00528 {
    00529 private:
    00530         void AssemblyComponentsFromXML( DOMElement &element )
    00531         {
    00532                 value = Attribute::value.Get( element );
    00533         }
    00534
    00535         bool DisassemblyComponentsToXML( DOMElement &element )
    00536         {
    00537                 Attribute::value.Set( element, value );
    00538                 return true;
    00539         }
    00540
    00541 protected:
    00542         ValuedUserInfo<T>( string userFriendlyTypeName )
    00543                 : TypedUserInfo<T>( userFriendlyTypeName )
    00544         {
    00545         }
    00546
    00547         ~ValuedUserInfo<T>()
    00548         {
    00549         }
    00550
    00552         string value;
    00553 };
    00554
    00576 class RootElement
    00577 {
    00578 private:
    00582         const AssertXercesIsAlive dummy;
    00583
    00585         DOMDocument* pDoc;
    00586
    00587         const XMLCh* const transcodedFileName;
    00588
    00590         DOMImplementation *pImplementation;
    00591
    00593         DOMWriter *pSerializer;
    00594
    00595         void Clean();
    00596
    00597 public:
    00599         RootElement(const char* fileName );
    00600
    00601         ~RootElement();
    00602
    00604         bool Load( void ) ;
    00605
    00607         void Save ( void );
    00608
    00610         operator DOMElement&();
    00611 };
    00612
    00613
    00617
    00618 class BoolUI: public ValuedUserInfo<bool>
    00619 {
    00620 private:
    00621
    00622         bool* AssemblyInstance()
    00623         {
    00624                 if( value == "true" )
    00625                         return new bool( true );
    00626                 else if( value == "false" )
    00627                         return new bool( false );
    00628                 else return NULL;
    00629         }
    00630
    00631         bool DisassemblyInstance(bool &instance)
    00632         {
    00633                 if( instance )
    00634                         value = "true";
    00635                 else
    00636                         value = "false";
    00637                 return true;
    00638         }
    00639
    00640 public:
    00641
    00642         BoolUI()
    00643                 : ValuedUserInfo<bool>("bool")
    00644         {
    00645         }
    00646 };
    00647
    00648
    00649 class IntUI: public ValuedUserInfo<int>
    00650 {
    00651 private:
    00652
    00653         int* AssemblyInstance()
    00654         {
    00655                 return new int( atoi( value.c_str()) );
    00656         }
    00657
    00658         bool DisassemblyInstance(int &instance)
    00659         {
    00660                 char buff[30];
    00661                 sprintf(buff, "%d", instance );
    00662                 value = buff;
    00663                 return true;
    00664         }
    00665
    00666 public:
    00667         IntUI():ValuedUserInfo<int>("int")
    00668         {
    00669         }
    00670 };
    00671
    00672
    00673
    00674 class DoubleUI: public ValuedUserInfo<double>
    00675 {
    00676 private:
    00677
    00678         double* AssemblyInstance()
    00679         {
    00680                 return new double( atof( value.c_str()) );
    00681         }
    00682
    00683         bool DisassemblyInstance(double &instance)
    00684         {
    00685                 char buff[30];
    00686                 sprintf(buff, "%f", instance );
    00687                 value = buff;
    00688                 return true;
    00689         }
    00690
    00691 public:
    00692         DoubleUI():ValuedUserInfo<double>("double")
    00693         {
    00694         }
    00695 };
    00696
    00697
    00698 class StringUI: public ValuedUserInfo<string>
    00699 {
    00700 private:
    00701         string* AssemblyInstance()
    00702         {
    00703                 return new string( value );
    00704         }
    00705
    00706         bool DisassemblyInstance(string &instance)
    00707         {
    00708                 value = instance;
    00709                 return true;
    00710         }
    00711
    00712 public:
    00713         StringUI():ValuedUserInfo<string>("string")
    00714         {
    00715         }
    00716 };
    00717
    00718
    00719 #endif // #ifndef UI_H