58 | | }; |
59 | | |
60 | | //! The only global instance of the GlobalXercesConnector class |
61 | | extern const GlobalXercesConnector XMLConnector; |
| 76 | |
| 77 | //! The only global instance of the XercesConnector class |
| 78 | // potrebujeme inicializaci hned v okamziku zavolani!! |
| 79 | static XercesConnector& instance() |
| 80 | { |
| 81 | static XercesConnector gxc; |
| 82 | return gxc; |
| 83 | }; |
| 84 | }; |
| 85 | |
| 86 | class BindingFrame |
| 87 | { |
| 88 | public: |
| 89 | // nacpe na prislusne pointery, kdyztak da NULL |
| 90 | virtual void AssemblyBindedData( DOMElement &element ) = 0; |
| 91 | |
| 92 | // uvolneni pameti po slozeni objektu, tj. lze jedine po AssemblyBD |
| 93 | virtual void ReleaseUsedMemory() = 0; |
| 94 | |
| 95 | // vrati bool, pokud se povedlo rozebrat a naplnit element |
| 96 | // nebude tu nahodou jeste ten help - string?? |
| 97 | virtual bool DisassemblyBindedData( DOMElement &element ) = 0; |
| 98 | }; |
73 | | //! Name which identifies the attribute among others related to the same XML-tag, |
74 | | //! must be unique within its context! |
75 | | XMLCh* const transcodedName; |
76 | | |
77 | | public: |
78 | | //! Type definition of mapping which transforms names to the related attributes |
79 | | typedef map<const XMLCh* const, Attribute* const, GlobalXercesConnector::Comparator> MappedAttributes; |
80 | | |
81 | | //! The only constructor which fills the transcodedName attribute |
82 | | Attribute( const string name ); |
83 | | //! Destructor |
84 | | ~Attribute(); |
85 | | |
86 | | //! Set accessor to this attribute converting input string into a properly-typed value |
87 | | virtual void Set( const string str ) = 0; |
88 | | //! Get accessor converting stored value into a string |
89 | | virtual const string Get() = 0; |
90 | | //! This method is the key method to connect the attribute to the related UI element |
91 | | void Attach( MappedAttributes &externalAttributes); |
92 | | //! This method add and DOMAttribute node to the DOMElement passed as an argument |
93 | | void FillAttribute(DOMElement &element); |
94 | | }; |
95 | | |
96 | | /*! |
97 | | @brief Class encapsulating all the necessary stuff to work with the double attribute |
98 | | */ |
99 | | class DoubleAttribute: public Attribute |
100 | | { |
101 | | public: |
102 | | double value; |
103 | | DoubleAttribute( const string name); |
104 | | void Set( const string str ); |
105 | | const string Get(); |
106 | | }; |
107 | | |
108 | | |
109 | | /*! |
110 | | @brief Class encapsulating all the necessary stuff to work with an int attribute |
111 | | */ |
112 | | class IntAttribute : public Attribute |
113 | | { |
114 | | public: |
115 | | int value; |
116 | | IntAttribute( const string name ); |
117 | | void Set( const string str ); |
118 | | const string Get(); |
119 | | }; |
120 | | |
121 | | /*! |
122 | | @brief Class encapsulating all the necessary stuff to work with a string attribute |
123 | | */ |
124 | | class StringAttribute : public Attribute |
125 | | { |
126 | | public: |
127 | | string value; |
128 | | StringAttribute( const string name ); |
129 | | void Set( const string str ); |
130 | | const string Get(); |
131 | | }; |
132 | | |
133 | | /*! |
134 | | @brief UserInfoCore class is for internal purposes only. Use UserInfo<T> instead. |
135 | | |
136 | | The raison d'etre of this class is to allow pointers to (the main part of) |
137 | | UserInfo<T> objects even for different generic types. |
138 | | */ |
139 | | class UserInfoCore |
140 | | { |
141 | | public: |
142 | | //! Fills internal attributes and descendant elements according DOMElement |
143 | | virtual void ParseElement(DOMElement *element) = 0; |
144 | | |
145 | | //! Fills DOMElement according internal attributes and descendant elements |
146 | | virtual void FillElement(DOMElement &element) = 0; |
147 | | }; |
148 | | |
149 | | /*! |
150 | | @brief The main user info template class |
151 | | |
152 | | You should derive this class whenever you need new UserInfo. |
153 | | */ |
154 | | template<typename T> class UserInfo : public UserInfoCore |
155 | | { |
156 | | private: |
157 | | //! Name which identifies the element among others related to the same XML-tag, |
158 | | //! must be unique within its context! |
159 | | XMLCh* transcodedName; |
| 111 | //! Type definition of mapping which transforms type names to the related user infors |
| 112 | typedef map< const string, UserInfo*> MappedName2UI; |
161 | | //! Type definition of mapping which transforms names to the related elements |
162 | | typedef map<const XMLCh* const, UserInfoCore* const, GlobalXercesConnector::Comparator> MappedElements; |
163 | | |
164 | | protected: |
165 | | //! MappiLength of the output vector |
166 | | MappedElements elements; |
167 | | //! Length of the output vector |
168 | | Attribute::MappedAttributes attributes; |
169 | | |
170 | | public: |
171 | | //! Explanation for an user is the only obligatory attribute |
172 | | StringAttribute help; |
173 | | |
174 | | //! The only constructor which fills both the transcodedName and the help attribute |
175 | | UserInfo<T>( |
176 | | const string name, |
177 | | const string help_msg = "" ) |
178 | | : help("help"), |
179 | | transcodedName( XMLString::transcode( name.c_str() ) ) |
| 114 | //! Mapped |
| 115 | static MappedName2UI& mappedName2UI() |
| 116 | { |
| 117 | static MappedName2UI var; |
| 118 | return var; |
| 119 | } |
| 120 | |
| 121 | const string underlyingTypeName; |
| 122 | |
| 123 | public: |
| 124 | |
| 125 | //! The only constructor which fills both the transcodedTypeName and the help attribute |
| 126 | UserInfo( const string& underlyingTypeName ) |
| 127 | : underlyingTypeName ( underlyingTypeName ) |
181 | | XMLString::upperCase( transcodedName ); |
182 | | help.Attach( attributes ); |
183 | | help.value = help_msg; |
184 | | }; |
185 | | //! Destructor |
186 | | ~UserInfo<T>() |
187 | | { |
188 | | XMLString::release( (XMLCh**)&transcodedName ); |
189 | | } |
190 | | |
191 | | //! returns object of templated type filled with data stored in this UserInfo instance |
192 | | virtual T* build(void) = 0; |
193 | | |
194 | | //! Save UserInfo to the file (typically with an XML extension) |
195 | | void Save ( char* fileName ) |
196 | | { |
197 | | XMLCh* transcodedFileName = XMLString::transcode( fileName ); |
198 | | LocalFileFormatTarget outputTarget( transcodedFileName ); |
199 | | XMLString::release( &transcodedFileName ); |
200 | | |
201 | | DOMDocument* pDoc = XMLConnector.pImplementation->createDocument( |
202 | | XMLString::transcode( "M3K USER INFO" ), |
203 | | XMLString::transcode( "ROOT" ), NULL ); |
204 | | DOMElement *pRoot = pDoc->getDocumentElement(); |
205 | | |
206 | | FillElement( *pRoot ); |
207 | | |
208 | | XMLConnector.pSerializer->writeNode( &outputTarget, *pDoc); |
209 | | delete pDoc; |
210 | | } |
211 | | //! Load UserInfo from the file (typically with an XML extension) |
212 | | void Load ( char* fileName ) |
213 | | { |
214 | | bool bFailed = false; |
215 | | |
216 | | try |
217 | | { |
218 | | XMLCh* transcodedFileName = XMLString::transcode( fileName ) ; |
219 | | const LocalFileInputSource inputSource( transcodedFileName ); |
220 | | XMLString::release( &transcodedFileName ); |
221 | | |
222 | | XMLConnector.pParser->parse( inputSource ); |
223 | | bFailed = ( XMLConnector.pParser->getErrorCount() != 0 ); |
224 | | } |
225 | | catch (...) |
226 | | { |
227 | | bFailed = true; |
228 | | } |
229 | | |
230 | | if( !bFailed) |
231 | | { |
232 | | DOMDocument *pDoc = XMLConnector.pParser->getDocument(); |
233 | | DOMElement *pRoot = pDoc->getDocumentElement(); |
234 | | bFailed = true; |
235 | | for( DOMNode* node = pRoot->getFirstChild(); node != NULL; node = node->getNextSibling() ) |
236 | | if( node->getNodeType() == DOMNode::ELEMENT_NODE ) |
237 | | { |
238 | | ParseElement( (DOMElement*) node ); |
239 | | bFailed = false; |
240 | | break; |
241 | | } |
242 | | } |
243 | | |
244 | | if( bFailed ) |
245 | | { |
246 | | // exception?! |
247 | | } |
248 | | } |
249 | | //! This method is the key method to connect the element to its parent UI element |
250 | | void Attach( MappedElements &externalElements) |
251 | | { |
252 | | pair<const XMLCh* const, UserInfoCore* const> newPair( transcodedName, this ); |
253 | | externalElements.insert(newPair); |
254 | | } |
| 129 | // trik, chci jen to, aby se inicializoval!! |
| 130 | XercesConnector::instance(); |
| 131 | |
| 132 | cout << underlyingTypeName; |
| 133 | |
| 134 | mappedName2UI().insert( make_pair( underlyingTypeName, this ) ); |
| 135 | } |
| 136 | |
| 137 | ~UserInfo() |
| 138 | { |
| 139 | } |
| 140 | |
| 141 | public: |
256 | | void ParseElement(DOMElement *element) |
257 | | { |
258 | | DOMNodeList* nodeList = element->getChildNodes(); |
259 | | if( nodeList ) |
260 | | for( int i = 0; i < nodeList->getLength(); i++ ) |
| 143 | virtual void BuildInternal(void* &pInstance) = 0; |
| 144 | |
| 145 | //! returns object of templated type filled with data stored in this CompoundUserInfo instance |
| 146 | // NULL if error.. |
| 147 | template<class T> |
| 148 | static void Assembly( const string tagName, DOMElement &element, T* &pInstance ) |
| 149 | { |
| 150 | pInstance = NULL; |
| 151 | |
| 152 | XMLCh* transcodedTagName = XMLString::transcode( tagName.c_str() ); |
| 153 | XMLString::upperCase( transcodedTagName ); |
| 154 | |
| 155 | /*///////////////////////// |
| 156 | DOMNodeList* nodeListe = element.getChildNodes(); |
| 157 | if( nodeListe ) |
| 158 | for( int i = 0; i < nodeListe->getLength(); i++ ) |
272 | | |
273 | | DOMNamedNodeMap* nodeMap = element->getAttributes(); |
274 | | if( nodeMap ) |
275 | | for( int i = 0; i < nodeMap->getLength(); i++ ) |
| 167 | getchar(); |
| 168 | |
| 169 | *///////////////////////////// |
| 170 | |
| 171 | |
| 172 | DOMNodeList* const nodeList = element.getElementsByTagName( transcodedTagName ); |
| 173 | XMLString::release( (XMLCh**)&transcodedTagName ); |
| 174 | |
| 175 | if( nodeList != NULL && nodeList->getLength() != 1 ) |
| 176 | return; |
| 177 | |
| 178 | // TAKZE MAME V RUCE ELEMENT SE JMENEM "tagName" |
| 179 | DOMElement* childElement = (DOMElement*) nodeList->item(0); |
| 180 | |
| 181 | // COZ O TO, UDELAL BYCH TO STATICKOU KONSTANTOU, ALE JAK JI PAK SMAZU?? |
| 182 | XMLCh* transcodedTypeAttributeName = XMLString::transcode("type"); |
| 183 | const XMLCh* const transcodedType = childElement->getAttribute( transcodedTypeAttributeName ); |
| 184 | XMLString::release( (XMLCh**)&transcodedTypeAttributeName ); |
| 185 | |
| 186 | if( !XMLString::stringLen( transcodedType ) ) |
| 187 | return; |
| 188 | |
| 189 | // TED MAME V RUCE JMENO TYPU Z ATRIBUTU TYPE |
| 190 | string type = XercesConnector::instance().XMLCh2str( transcodedType ); |
| 191 | |
| 192 | MappedName2UI::const_iterator iter = mappedName2UI().find( type ); |
| 193 | if( iter == mappedName2UI().end()) |
| 194 | return; |
| 195 | |
| 196 | // A TED PRISLUSNE UI |
| 197 | UserInfo *relatedUI = iter->second; |
| 198 | relatedUI->AssemblyBindedData( *childElement ); |
| 199 | relatedUI->BuildInternal( (void*&)pInstance ); |
| 200 | relatedUI->ReleaseUsedMemory(); |
| 201 | |
| 202 | if( pInstance == NULL ) |
| 203 | return; |
| 204 | |
| 205 | try |
| 206 | { |
| 207 | // takhle to zkontroluju? name musi byt shodne s name nahore!! |
| 208 | // takze mame typ T, ale name bud od jeho potomka.. oki?? |
| 209 | string resultingType = typeid( *pInstance ).name(); |
| 210 | if( resultingType != type ) |
277 | | DOMNode* node = nodeMap->item(i); |
278 | | if( node->getNodeType() == DOMNode::ATTRIBUTE_NODE ) |
| 212 | cout << "FATAL ERROR!!" << endl; |
| 213 | pInstance = NULL; |
| 214 | } |
| 215 | } |
| 216 | catch(...) |
| 217 | { |
| 218 | // delete? ale jak na to? asi tezko |
| 219 | pInstance = NULL; |
| 220 | } |
| 221 | return; |
| 222 | } |
| 223 | |
| 224 | // ? pri destrukci si za ne naopak zodpovida ten, kdo je vytvoril.. protoze |
| 225 | // budou zit v tom objektu!! tak jakapak destrkuce.. |
| 226 | }; |
| 227 | |
| 228 | |
| 229 | template<typename T> class TypedUserInfo : public UserInfo |
| 230 | { |
| 231 | protected: |
| 232 | |
| 233 | //! The only constructor which fills |
| 234 | TypedUserInfo<T>( ) |
| 235 | : UserInfo( typeid(T).name() ) |
| 236 | { |
| 237 | }; |
| 238 | |
| 239 | //! Destructor |
| 240 | ~TypedUserInfo<T>() |
| 241 | { |
| 242 | } |
| 243 | |
| 244 | public: |
| 245 | // FRIEND radeji |
| 246 | void BuildInternal(void* &pInstance) |
| 247 | { |
| 248 | T* &pTypedInstance = (T*&) pInstance; |
| 249 | Build( pTypedInstance ); |
| 250 | } |
| 251 | |
| 252 | virtual void Build(T* &pTypedInstance) = 0; |
| 253 | |
| 254 | static const TypedUserInfo<T> &instance; |
| 255 | }; |
| 256 | |
| 257 | |
| 258 | |
| 259 | /*! |
| 260 | @brief The main user info template class |
| 261 | |
| 262 | You should derive this class whenever you need new CompoundUserInfo. |
| 263 | */ |
| 264 | template<typename T> class CompoundUserInfo : public TypedUserInfo<T> |
| 265 | { |
| 266 | private: |
| 267 | //! Mapped elements, i.e., descendant html tags |
| 268 | vector<BindingFrame* const> bindedElements; |
| 269 | |
| 270 | protected: |
| 271 | template<typename U> class BindedType: public BindingFrame |
| 272 | { |
| 273 | private: |
| 274 | const TypedUserInfo<U> &factory; |
| 275 | string name; |
| 276 | string help; |
| 277 | |
| 278 | public: |
| 279 | U* pInstance; |
| 280 | |
| 281 | BindedType<U>( CompoundUserInfo<T> *parent, string name, string help ) |
| 282 | : name( name), help(help) |
| 283 | factory( TypedUserInfo<U>::instance ) |
| 284 | { |
| 285 | parent->bindedElements.push_back( this ); |
| 286 | pInstance = NULL; |
| 287 | } |
| 288 | |
| 289 | BindedType<U>( CompoundUserInfo<T> *parent, string name ) |
| 290 | : name( name), help(""), |
| 291 | factory( TypedUserInfo<U>::instance ) |
| 292 | { |
| 293 | parent->bindedElements.push_back( this ); |
| 294 | pInstance = NULL; |
| 295 | } |
| 296 | |
| 297 | void AssemblyBindedData( DOMElement &element ) |
| 298 | { |
| 299 | factory.Assembly( pInstance, element, name ); |
| 300 | } |
| 301 | |
| 302 | void ReleaseUsedMemory() |
| 303 | { |
| 304 | if( pInstance != NULL ) |
| 305 | delete pInstance; |
| 306 | } |
| 307 | |
| 308 | bool DisassemblyBindedData( DOMElement &element ) |
| 309 | { |
| 310 | // return factory.Disassembly( (void*&) pInstance, element, name, help ); |
| 311 | return true; |
| 312 | } |
| 313 | }; |
| 314 | |
| 315 | |
| 316 | public: |
| 317 | |
| 318 | void AssemblyBindedData( DOMElement &element ) |
| 319 | { |
| 320 | for( unsigned int ind = 0; ind < bindedElements.size(); ind++ ) |
| 321 | bindedElements[ind]->AssemblyBindedData( element ); |
| 322 | } |
| 323 | |
| 324 | void ReleaseUsedMemory() |
| 325 | { |
| 326 | for( unsigned int ind = 0; ind < bindedElements.size(); ind++ ) |
| 327 | bindedElements[ind]->ReleaseUsedMemory(); |
| 328 | } |
| 329 | |
| 330 | bool DisassemblyBindedData( DOMElement &element ) |
| 331 | { |
| 332 | for( unsigned int ind = 0; ind < bindedElements.size(); ind++ ) |
| 333 | if( !bindedElements[ind]->DisassemblyBindedData( element ) ) |
| 334 | return false; |
| 335 | return true; |
| 336 | } |
| 337 | }; |
| 338 | |
| 339 | |
| 340 | /* |
| 341 | //! returns object of templated type filled with data stored in this CompoundUserInfo instance |
| 342 | bool Disassembly(void * &pInstance, DOMElement &element, string name, char * help = "" ) |
| 343 | { |
| 344 | T* &pTypedInstance = (T*&) pInstance; |
| 345 | // do elementu prida vetev se jmenem name a vyplni obsahujici data z instance |
| 346 | // zde nemuze vzniknout zadna chyba, ponevadz XML vytvarime |
| 347 | |
| 348 | /* |
| 349 | for( MappedElements::const_iterator iter = elements.begin(); iter != elements.end(); iter++) |
| 350 | { |
| 351 | iter->second->AppendElement( *pHead ); |
290 | | } |
291 | | |
292 | | void FillElement(DOMElement &element) |
293 | | { |
294 | | DOMDocument* pDoc = element.getOwnerDocument(); |
295 | | |
296 | | DOMElement* pHead = pDoc->createElement( transcodedName ); |
297 | | element.appendChild( pHead ); |
298 | | |
299 | | for( MappedElements::const_iterator iter = elements.begin(); iter != elements.end(); iter++) |
300 | | iter->second->FillElement( *pHead ); |
301 | | |
302 | | for( Attribute::MappedAttributes::iterator iter = attributes.begin(); iter != attributes.end(); iter++) |
303 | | iter->second->FillAttribute( *pHead ); |
304 | | } |
305 | | }; |
| 361 | |
| 362 | for( MappedAttributes::iterator iter = attributes.begin(); iter != attributes.end(); iter++) |
| 363 | { |
| 364 | // we do not create attributes, which are empty |
| 365 | if( !strcmp( iter->second->c_str(), "") ) |
| 366 | continue; |
| 367 | |
| 368 | DOMDocument* pDoc = pHead->getOwnerDocument(); |
| 369 | DOMAttr* pAttribute = pDoc->createAttribute( iter->first ); |
| 370 | |
| 371 | XMLCh* transcodedValue = XMLString::transcode( iter->second->c_str() ); |
| 372 | pAttribute->setValue( transcodedValue ); |
| 373 | XMLString::release( &transcodedValue ); |
| 374 | |
| 375 | pHead->setAttributeNode(pAttribute); |
| 376 | } |
| 377 | return true; |
| 378 | } |
| 379 | */ |
| 380 | |
| 381 | |
| 382 | template<typename T> class ValuedUserInfo : public TypedUserInfo<T> |
| 383 | { |
| 384 | |
| 385 | private: |
| 386 | const XMLCh* const transcodedValueName; |
| 387 | |
| 388 | public: |
| 389 | // Value nemusi byt pointer, na rozdil od ostatnich binding framu.. |
| 390 | string value; |
| 391 | |
| 392 | ValuedUserInfo<T>() |
| 393 | : transcodedValueName( XMLString::transcode( "value" )) |
| 394 | { |
| 395 | } |
| 396 | |
| 397 | ~ValuedUserInfo<T>() |
| 398 | { |
| 399 | XMLString::release( (XMLCh**)&transcodedValueName ); |
| 400 | } |
| 401 | |
| 402 | void AssemblyBindedData( DOMElement &element ) |
| 403 | { |
| 404 | const XMLCh* const transcodedValue = element.getAttribute( transcodedValueName ); |
| 405 | value = XercesConnector::instance().XMLCh2str( transcodedValue ); |
| 406 | } |
| 407 | |
| 408 | void ReleaseUsedMemory() |
| 409 | { |
| 410 | } |
| 411 | |
| 412 | bool DisassemblyBindedData( DOMElement &element ) |
| 413 | { |
| 414 | // if( value.length()==0 ) |
| 415 | // return false; |
| 416 | return true; |
| 417 | } |
| 418 | }; |
| 419 | |
| 420 | |
| 421 | class RootElement |
| 422 | { |
| 423 | // umi se pretypovat na DOMElement &element |
| 424 | // a to vzdy, save a load se muze udelat az pak!! |
| 425 | |
| 426 | private: |
| 427 | DOMElement * pRoot; |
| 428 | DOMDocument* pDoc; |
| 429 | |
| 430 | const XMLCh* const transcodedFileName ; |
| 431 | |
| 432 | public: |
| 433 | |
| 434 | RootElement( char* fileName ) |
| 435 | : transcodedFileName( XMLString::transcode( fileName ) ) |
| 436 | { |
| 437 | pDoc = XercesConnector::instance().pImplementation->createDocument( |
| 438 | XMLString::transcode( "M3K USER INFO" ), |
| 439 | XMLString::transcode( "ROOT" ), NULL ); |
| 440 | pRoot = pDoc->getDocumentElement(); |
| 441 | } |
| 442 | |
| 443 | ~RootElement() |
| 444 | { |
| 445 | XMLString::release( (XMLCh**)&transcodedFileName ); |
| 446 | if( pDoc ) |
| 447 | delete pDoc; |
| 448 | } |
| 449 | |
| 450 | //! loads root element from a file |
| 451 | bool Load( void ) |
| 452 | { |
| 453 | const LocalFileInputSource inputSource( transcodedFileName ); |
| 454 | DOMDocument * newDoc = XercesConnector::instance().Parse( inputSource ); |
| 455 | if( newDoc == NULL ) |
| 456 | return false; |
| 457 | |
| 458 | if( pDoc ) |
| 459 | delete pDoc; |
| 460 | |
| 461 | pDoc = newDoc; |
| 462 | pRoot = pDoc->getDocumentElement(); |
| 463 | return true; |
| 464 | } |
| 465 | |
| 466 | |
| 467 | //! Save UserInfo to the file (typically with an XML extension) |
| 468 | void Save ( void ) |
| 469 | { |
| 470 | LocalFileFormatTarget outputTarget( transcodedFileName ); |
| 471 | XercesConnector::instance().pSerializer->writeNode( &outputTarget, *pDoc); |
| 472 | } |
| 473 | |
| 474 | operator DOMElement&() |
| 475 | { |
| 476 | return *pRoot; |
| 477 | } |
| 478 | }; |
| 479 | |