userinfo.h sstream iostream stdio.h string typeinfo map utility vector xercesc/dom/DOM.hpp xercesc/util/PlatformUtils.hpp xercesc/util/XMLString.hpp xercesc/framework/LocalFileFormatTarget.hpp xercesc/framework/LocalFileInputSource.hpp xercesc/dom/DOMWriter.hpp xercesc/parsers/XercesDOMParser.hpp work/git/mixpp/bdm/userinfo.cpp work/git/mixpp/tests/testUI.cpp AssertXercesIsAlive AssertXercesIsAlive::XercesConnector BindingFrame Attribute UserInfo UserInfo::StringToUIMap TypedUserInfo CompoundUserInfo CompoundUserInfo::BindedElement ValuedUserInfo RootElement BoolUI IntUI DoubleUI StringUI #ifndefUI_H #defineUI_H #include<sstream> #include<iostream> #include<stdio.h> #include<string> #include<typeinfo> #include<map> #include<utility> #include<vector> #include<xercesc/dom/DOM.hpp> #include<xercesc/util/PlatformUtils.hpp> #include<xercesc/util/XMLString.hpp> #include<iostream> #include<xercesc/framework/LocalFileFormatTarget.hpp> #include<xercesc/framework/LocalFileInputSource.hpp> #include<xercesc/dom/DOMWriter.hpp> #include<xercesc/parsers/XercesDOMParser.hpp> #ifdefXERCES_CPP_NAMESPACE_USE XERCES_CPP_NAMESPACE_USE #endif usingstd::string; usingnamespacestd; classAssertXercesIsAlive { private: classXercesConnector { private: XercesConnector() { //initializetheXMLlibrary XMLPlatformUtils::Initialize(); } ~XercesConnector() { //terminatetheXMLlibrary XMLPlatformUtils::Terminate(); } public: staticvoidStayAlive() { staticXercesConnectorxc; }; }; public: AssertXercesIsAlive() { XercesConnector::StayAlive(); } }; classBindingFrame { private: AssertXercesIsAlivedummy; protected: BindingFrame(); stringXMLCh2str(constXMLCh*constXMLCh_str); stringremoveSpaces(conststring&str) { std::stringtemp; for(unsignedinti=0;i<str.length();i++) if(str[i]=='')temp+='_'; elsetemp+=str[i]; returntemp; } public: virtualvoidAssemblyComponentsFromXML(DOMElement&element)=0; virtualvoidReleaseMemory(){} virtualboolDisassemblyComponentsToXML(DOMElement&element)=0; }; classAttribute { private: AssertXercesIsAlivedummy; constXMLCh*consttranscodedAttributeName; public: Attribute(stringattributeName); ~Attribute(); string&Get(DOMElement&element)const; voidSet(DOMElement&element,conststring&str)const; staticconstAttributehelp; staticconstAttributetype; staticconstAttributevalue; }; classUserInfo:protectedBindingFrame { private: typedefUserInfo*constpUserInfo; classStringToUIMap { private: typedefmap<conststring,pUserInfo>MappedString2UI; staticMappedString2UI&privateMap(); public: staticvoidAdd(stringkey,pUserInfopInstance); staticpUserInfoRetrieve(stringkey); }; virtualvoid*AssemblyTypelessInstance()=0; virtualboolDisassemblyTypelessInstance(void*pInstance)=0; conststringuserFriendlyTypeName; conststringtypeNameByRTTI; protected: UserInfo(conststring&userFriendlyTypeName,conststring&typeNameByRTTI) :userFriendlyTypeName(removeSpaces(userFriendlyTypeName)), typeNameByRTTI(typeNameByRTTI) { StringToUIMap::Add(userFriendlyTypeName,this); if(userFriendlyTypeName!=typeNameByRTTI) //wehaveacommonmapforbothgroupsofnames, //therefore,itisnousetoaddthesamepairagain StringToUIMap::Add(typeNameByRTTI,this); } public: template<classT> staticT*Assembly(DOMElement&element,conststringtagName) { XMLCh*transcodedTagName=XMLString::transcode(tagName.c_str()); XMLString::upperCase(transcodedTagName); DOMNodeList*constnodeList=element.getElementsByTagName(transcodedTagName); XMLString::release((XMLCh**)&transcodedTagName); if(!nodeList||nodeList->getLength()==0) { cerr<<"Warning:thereisnotanytagnamed"""<<tagName<<"""inthepassedDOMelementofaXMLdocmument!"; returnNULL; } if(nodeList->getLength()>1) { cerr<<"Warning:thereistomanyelementsnamed"""<<tagName<<"""inthepassedDOMelementofaXMLdocmument.Butthetagnamehastobeunique!"; returnNULL; } //thistimeweholdanelementwiththesamenameasthetagNameis DOMElement*pTheOnlyElement=(DOMElement*)nodeList->item(0); //wegetaveluestoredinthe"type"attribute stringuserFriendlyTypeName=Attribute::type.Get(*pTheOnlyElement); //andfinallywefindaUserInforelatedtothistype pUserInfopRelatedUI=StringToUIMap::Retrieve(userFriendlyTypeName); if(!pRelatedUI) { cerr<<"Warning:thereisnotanyUserInforelatedtotypenamed"""<<userFriendlyTypeName<<""",instanceassemblingterminated!"; returnNULL; } //prepareallcomponentsnecessaryforaninstanceassembling pRelatedUI->AssemblyComponentsFromXML(*pTheOnlyElement); //instanceassembling void*pTypelessInstance=pRelatedUI->AssemblyTypelessInstance(); //cleaningup pRelatedUI->ReleaseMemory(); if(pTypelessInstance==NULL) { cerr<<"Warning:therewassomeerrorwhenparsingaXMLdocument,instanceassemblingterminated!"; returnNULL; } T*pInstance=NULL; try { //a"doityourself"typecheck:) pInstance=(T*)pTypelessInstance; stringresultingTypeNameByRTTI=typeid(*pInstance).name(); if(resultingTypeNameByRTTI!=pRelatedUI->typeNameByRTTI) pInstance=NULL; } catch(...) { pInstance=NULL; } if(pInstance==NULL) cerr<<"Warning:UserInforelatedtotype"""<<userFriendlyTypeName<<"""havejustreturnedinstanceofadifferenttype!Instanceassemblingterminated!"; returnpInstance; } template<classT> staticboolDisassembly(T&instance,DOMElement&element,conststringtagName,conststringhelp) { pUserInfopRelatedUI=StringToUIMap::Retrieve(typeid(instance).name()); if(!pRelatedUI) returnfalse; //addanewelementnamedaccordingthepassedtagName XMLCh*transcodedTagName=XMLString::transcode(tagName.c_str()); XMLString::upperCase(transcodedTagName); DOMDocument*pDoc=element.getOwnerDocument(); DOMElement*pCreatedElement=pDoc->createElement(transcodedTagName); element.appendChild(pCreatedElement); XMLString::release((XMLCh**)&transcodedTagName); //addattributes"type"and"help" Attribute::type.Set(*pCreatedElement,pRelatedUI->userFriendlyTypeName); Attribute::help.Set(*pCreatedElement,help); //disassemblyinstanceitselfintoitscomponents boolresult=pRelatedUI->DisassemblyTypelessInstance((void*)&instance); if(result) //disassemblyallcomponentsofaninstance result=pRelatedUI->DisassemblyComponentsToXML(*pCreatedElement); returnresult; } template<classT> staticboolDisassembly(T&instance,DOMElement&element,conststringtagName) { returnDisassembly(instance,element,tagName,""); } }; template<typenameT>classTypedUserInfo:publicUserInfo { private: boolDisassemblyTypelessInstance(void*pInstance) { try { returnDisassemblyInstance(*(T*)pInstance); } catch(...) { returnfalse; } } void*AssemblyTypelessInstance() { return(void*)AssemblyInstance(); } virtualT*AssemblyInstance()=0; virtualboolDisassemblyInstance(T&instance)=0; protected: TypedUserInfo<T>(conststring&userFriendlyTypeName) :UserInfo(userFriendlyTypeName,typeid(T).name()) { }; ~TypedUserInfo<T>() { } staticconstTypedUserInfo<T>&instance; }; template<typenameT>classCompoundUserInfo:publicTypedUserInfo<T> { private: vector<BindingFrame*>bindedElements; protected: template<typenameU>classBindedElement:publicBindingFrame { private: stringname; stringhelp; boolrelease; U*pValue; constUdefaultValue; public: Uvalue; BindedElement<U>(CompoundUserInfo<T>*parent,stringname,UdefaultValue,stringhelp) :name(removeSpaces(name)),help(help),defaultValue(defaultValue) { parent->bindedElements.push_back(this); pValue=NULL; value=defaultValue; } BindedElement<U>(CompoundUserInfo<T>*parent,stringname,UdefaultValue) :name(removeSpaces(name)),help(""),defaultValue(defaultValue),value(defaultValue) { parent->bindedElements.push_back(this); pValue=NULL; value=defaultValue; } ~BindedElement<U>() { } voidAssemblyComponentsFromXML(DOMElement&element) { pValue=UserInfo::Assembly<U>(element,name); if(pValue)value=*pValue; } voidReleaseMemory() { if(pValue!=NULL) deletepValue; } boolDisassemblyComponentsToXML(DOMElement&element) { returnUserInfo::Disassembly(value,element,name,help); } }; private: voidAssemblyComponentsFromXML(DOMElement&element) { for(unsignedintind=0;ind<bindedElements.size();ind++) bindedElements[ind]->AssemblyComponentsFromXML(element); } voidReleaseMemory() { for(unsignedintind=0;ind<bindedElements.size();ind++) bindedElements[ind]->ReleaseMemory(); } boolDisassemblyComponentsToXML(DOMElement&element) { for(unsignedintind=0;ind<bindedElements.size();ind++) if(!bindedElements[ind]->DisassemblyComponentsToXML(element)) returnfalse; returntrue; } protected: CompoundUserInfo<T>(stringuserFriendlyTypeName) :TypedUserInfo<T>(userFriendlyTypeName) { } }; template<typenameT>classValuedUserInfo:publicTypedUserInfo<T> { private: voidAssemblyComponentsFromXML(DOMElement&element) { value=Attribute::value.Get(element); } boolDisassemblyComponentsToXML(DOMElement&element) { Attribute::value.Set(element,value); returntrue; } protected: ValuedUserInfo<T>(stringuserFriendlyTypeName) :TypedUserInfo<T>(userFriendlyTypeName) { } ~ValuedUserInfo<T>() { } stringvalue; }; classRootElement { private: constAssertXercesIsAlivedummy; DOMDocument*pDoc; constXMLCh*consttranscodedFileName; DOMImplementation*pImplementation; DOMWriter*pSerializer; voidClean(); public: RootElement(char*fileName); ~RootElement(); boolLoad(void); voidSave(void); operator DOMElement&(); }; classBoolUI:publicValuedUserInfo<bool> { private: bool*AssemblyInstance() { if(value=="true") returnnewbool(true); elseif(value=="false") returnnewbool(false); elsereturnNULL; } boolDisassemblyInstance(bool&instance) { if(instance) value="true"; else value="false"; returntrue; } public: BoolUI() :ValuedUserInfo<bool>("bool") { } }; classIntUI:publicValuedUserInfo<int> { private: int*AssemblyInstance() { returnnewint(atoi(value.c_str())); } boolDisassemblyInstance(int&instance) { charbuff[30]; sprintf(buff,"%d",instance); value=buff; returntrue; } public: IntUI():ValuedUserInfo<int>("int") { } }; classDoubleUI:publicValuedUserInfo<double> { private: double*AssemblyInstance() { returnnewdouble(atof(value.c_str())); } boolDisassemblyInstance(double&instance) { charbuff[30]; sprintf(buff,"%f",instance); value=buff; returntrue; } public: DoubleUI():ValuedUserInfo<double>("double") { } }; classStringUI:publicValuedUserInfo<string> { private: string*AssemblyInstance() { returnnewstring(value); } boolDisassemblyInstance(string&instance) { value=instance; returntrue; } public: StringUI():ValuedUserInfo<string>("string") { } }; #endif//#ifndefUI_H