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
00052 XMLPlatformUtils::Initialize();
00053 }
00054
00055 ~XercesConnector()
00056 {
00057
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
00217
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
00246 DOMElement* pTheOnlyElement = (DOMElement*) nodeList->item(0);
00247
00248
00249 string userFriendlyTypeName = Attribute::type.Get( *pTheOnlyElement );
00250
00251
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
00260 pRelatedUI->AssemblyComponentsFromXML( *pTheOnlyElement );
00261
00262
00263 void* pTypelessInstance = pRelatedUI->AssemblyTypelessInstance();
00264
00265
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
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
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
00312 Attribute::type.Set( *pCreatedElement, pRelatedUI->userFriendlyTypeName );
00313 Attribute::help.Set( *pCreatedElement, help );
00314
00315
00316 bool result = pRelatedUI->DisassemblyTypelessInstance( (void*) &instance );
00317 if( result )
00318
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