1 /* 2 * Copyright 2006 Sony Computer Entertainment Inc. 3 * 4 * Licensed under the MIT Open Source License, for details please see license.txt or the website 5 * http://www.opensource.org/licenses/mit-license.php 6 * 7 */ 8 9 #include <modules/daeSTLDatabase.h> 10 #include <dae/daeMetaElement.h> 11 12 using namespace std; 13 14 daeSTLDatabase::daeSTLDatabase(DAE& dae) : daeDatabase(dae) 15 { } 16 17 daeSTLDatabase::~daeSTLDatabase() 18 { 19 clear(); 20 } 21 22 daeInt daeSTLDatabase::setMeta(daeMetaElement *_topMeta) 23 { 24 topMeta = _topMeta; 25 return DAE_OK; 26 } 27 28 daeBool 29 daeSTLDatabase::isDocumentLoaded(daeString name) 30 { 31 daeDocument* document = getDocument(name); 32 if(document) 33 return(true); 34 else 35 return(false); 36 } 37 38 // Element Types of all Elements 39 daeUInt daeSTLDatabase::getTypeCount() 40 { 41 return (daeUInt)elements.size(); 42 } 43 44 45 daeString daeSTLDatabase::getTypeName(daeUInt index) 46 { 47 daeUInt count = 0; 48 49 map<string, vector< daeElement* > >::iterator iter = elements.begin(); 50 map<string, vector< daeElement* > >::iterator end = elements.end(); 51 while ( iter != end ) 52 { 53 if ( count == index ) 54 { 55 return (*iter).first.c_str(); 56 } 57 ++count; 58 ++iter; 59 } 60 61 return NULL; 62 } 63 64 // Documents 65 daeInt daeSTLDatabase::insertDocument(const char *name, daeElement* dom, daeDocument** document, bool zaeRootDocument, const std::string& extractedFileURI) 66 { 67 return createDocument( name, dom, document, zaeRootDocument, extractedFileURI ); 68 } 69 daeInt daeSTLDatabase::createDocument(const char *name, daeElement* dom, daeDocument** document, bool zaeRootDocument, const std::string& extractedFileURI) 70 { 71 // If a document already exists with the same name, error 72 if(isDocumentLoaded(name)) 73 { 74 if (document) 75 *document = NULL; 76 return DAE_ERR_COLLECTION_ALREADY_EXISTS; 77 } 78 79 // Make a new document 80 daeDocument *newDocument = new daeDocument(dae, zaeRootDocument, extractedFileURI); 81 newDocument->getDocumentURI()->setURI(name); 82 newDocument->setDomRoot(dom); 83 // Push the connection into the database 84 documents.push_back(newDocument); 85 86 if (document) 87 *document = newDocument; 88 89 return DAE_OK; 90 } 91 // !!!GAC revised version of insertDocument, creates a domCollada and fills it in for you. 92 daeInt daeSTLDatabase::insertDocument(const char *name, daeDocument** document) 93 { 94 return createDocument( name, document ); 95 } 96 daeInt daeSTLDatabase::createDocument(const char *name, daeDocument** document) 97 { 98 99 // If a document already exists with the same name, error 100 if(isDocumentLoaded(name)) 101 { 102 if (document) 103 *document = NULL; 104 return DAE_ERR_COLLECTION_ALREADY_EXISTS; 105 } 106 // Make the new document 107 daeDocument *newDocument = new daeDocument(dae); 108 // Make a domCOLLADA to be the root of this new document (this makes a reference so the domCOLLADA won't delete itself 109 daeElementRef myCOLLADA = topMeta->create(); 110 myCOLLADA->setDocument(newDocument); 111 newDocument->getDocumentURI()->setURI(name); 112 newDocument->setDomRoot(myCOLLADA); 113 114 // Add this document to the list. 115 documents.push_back(newDocument); 116 // If the user gave us a place to put the document, send it back to them. 117 if (document) 118 *document = newDocument; 119 120 return DAE_OK; 121 } 122 123 daeInt daeSTLDatabase::insertDocument( daeDocument *c ) { 124 documents.push_back(c); 125 insertElement( c, c->getDomRoot() ); 126 return DAE_OK; 127 } 128 129 daeInt daeSTLDatabase::removeDocument(daeDocument *document) 130 { 131 vector< daeDocument* >::iterator iter = documents.begin(); 132 while ( iter != documents.end() ) { 133 if ( (*iter) == document ) { 134 //delete all of its children 135 removeElement( *iter, (*iter)->getDomRoot() ); 136 delete *iter; // sthomas (see bug 1466019) 137 iter = documents.erase(iter); 138 } 139 else { 140 iter++; 141 } 142 } 143 return DAE_OK; 144 } 145 146 daeUInt daeSTLDatabase::getDocumentCount() 147 { 148 return (daeUInt)documents.size(); 149 } 150 151 daeDocument* daeSTLDatabase::getDocument(daeUInt index) 152 { 153 if (index<documents.size()) 154 return (documents[index]); 155 else 156 return NULL; 157 } 158 159 daeDocument* daeSTLDatabase::getDocument(daeString name_, bool skipUriNormalization) 160 { 161 string name = name_; 162 if (!skipUriNormalization) { 163 // Normalize the input string to an absolute URI with no fragment 164 name = daeURI(dae, name, true).str(); 165 } 166 167 // Try to find a document that matches 168 daeDocument *document; 169 int documentCount = getDocumentCount(); 170 for (int i=0;i<documentCount;i++) 171 { 172 document = getDocument(i); 173 if(document->getDocumentURI()->str() == name) 174 return(document); 175 } 176 return(NULL); 177 } 178 179 daeString daeSTLDatabase::getDocumentName(daeUInt index) 180 { 181 if (index<documents.size()) 182 return getDocument(index)->getDocumentURI()->getURI(); 183 else 184 return NULL; 185 } 186 187 // Elements 188 daeInt daeSTLDatabase::insertElement(daeDocument* document,daeElement* element) 189 { 190 insertChildren( document, element ); 191 192 map<string, vector< daeElement* > >::iterator iter = elements.find( string( element->getTypeName() ) ); 193 if ( iter != elements.end() ) 194 { 195 (*iter).second.push_back( element ); 196 } 197 else 198 { 199 vector< daeElement* > vec; 200 vec.push_back( element ); 201 elements.insert( make_pair( string( element->getTypeName() ), vec ) ); 202 } 203 204 // Insert into the type ID map 205 typeMap.insert(make_pair(element->typeID(), element)); 206 207 //insert into IDMap if element has an ID. IDMap is used to speed up URI resolution 208 if ( element->getID() != NULL ) { 209 elementsIDMap.insert( make_pair( string( element->getID() ), element ) ); 210 } 211 212 // Insert into sid map if the element has a sid 213 // string sid = element->getAttribute("sid"); 214 // if (!sid.empty()) 215 // sidMap.insert(sidMapPair(sid, element)); 216 217 dae.getSidRefCache().clear(); 218 219 return DAE_OK; 220 } 221 222 daeInt daeSTLDatabase::insertChildren( daeDocument *c, daeElement *element ) 223 { 224 daeElementRefArray era; 225 element->getChildren( era ); 226 for ( unsigned int i = 0; i < era.getCount(); i++ ) { 227 insertElement( c, era[i] ); 228 } 229 return DAE_OK; 230 } 231 232 daeInt daeSTLDatabase::removeElement(daeDocument* document,daeElement* element) 233 { 234 if ( !element ) { 235 return DAE_ERR_INVALID_CALL; 236 } 237 removeChildren( document, element ); 238 239 map<string, vector< daeElement* > >::iterator iter = elements.find( string( element->getTypeName() ) ); 240 if ( iter != elements.end() ) 241 { 242 vector< daeElement* > &vec = (*iter).second; 243 vector< daeElement* >::iterator i = vec.begin(); 244 vector< daeElement* >::iterator end = vec.end(); 245 while( i != end ) 246 { 247 if ( (*i) == element ) 248 { 249 vec.erase( i ); 250 break; 251 } 252 ++i; 253 } 254 } 255 256 typeMapRange range = typeMap.equal_range(element->typeID()); 257 for (typeMapIter iter = range.first; iter != range.second; iter++) { 258 if (iter->second == element) { 259 typeMap.erase(iter); 260 break; 261 } 262 } 263 264 if ( element->getID() != NULL ) { 265 idMapRange range = elementsIDMap.equal_range( string( element->getID() ) ); 266 multimap<string, daeElement* >::iterator iter = range.first; 267 while( iter != range.second ) { 268 if ( (*iter).second == element ) { 269 elementsIDMap.erase( iter ); 270 break; 271 } 272 ++iter; 273 } 274 } 275 276 // string sid = element->getAttribute("sid"); 277 // if (!sid.empty()) { 278 // pair<sidMapIter, sidMapIter> range = sidMap.equal_range(sid); 279 // for (sidMapIter iter = range.first; iter != range.second; iter++) { 280 // if (iter->second == element) { 281 // sidMap.erase(iter); 282 // break; 283 // } 284 // } 285 // } 286 287 dae.getSidRefCache().clear(); 288 289 return DAE_OK; 290 } 291 292 daeInt daeSTLDatabase::removeChildren( daeDocument *c, daeElement *element ) 293 { 294 daeElementRefArray era; 295 element->getChildren( era ); 296 for ( unsigned int i = 0; i < era.getCount(); i++ ) { 297 removeElement( c, era[i] ); 298 } 299 return DAE_OK; 300 } 301 302 daeInt daeSTLDatabase::changeElementID( daeElement* element, daeString newID ) 303 { 304 if ( !element ) { 305 return DAE_ERR_INVALID_CALL; 306 } 307 308 // Remove the current entry in the ID map if the element has an ID 309 if ( element->getID() != NULL ) { 310 pair< multimap<string, daeElement* >::iterator, multimap<string, daeElement* >::iterator> range; 311 range = elementsIDMap.equal_range( string( element->getID() ) ); 312 multimap<string, daeElement* >::iterator iter = range.first; 313 while( iter != range.second ) { 314 if ( (*iter).second == element ) { 315 elementsIDMap.erase( iter ); 316 break; 317 } 318 ++iter; 319 } 320 } 321 322 // Add an entry to the ID map if the element will have an ID 323 if ( newID != NULL ) { 324 elementsIDMap.insert( make_pair( string( newID ), element ) ); 325 } 326 327 dae.getSidRefCache().clear(); 328 329 return DAE_OK; 330 } 331 332 daeInt daeSTLDatabase::changeElementSID(daeElement* element, daeString newSID) { 333 if (!element) 334 return DAE_ERR_INVALID_CALL; 335 336 // // Remove the current entry in the sid map if the element has a sid 337 // string sid = element->getAttribute("sid"); 338 // if (!sid.empty()) { 339 // pair<sidMapIter, sidMapIter> range = sidMap.equal_range(sid); 340 // for (sidMapIter iter = range.first; iter != range.second; iter++) { 341 // if (iter->second == element) { 342 // sidMap.erase(iter); 343 // break; 344 // } 345 // } 346 // } 347 348 // // Add an entry to the sid map if the element will have a sid 349 // if ( newSID != NULL ) 350 // sidMap.insert(sidMapPair(newSID, element)); 351 352 dae.getSidRefCache().clear(); 353 354 return DAE_OK; 355 } 356 357 daeInt daeSTLDatabase::clear() 358 { 359 elements.clear(); 360 typeMap.clear(); 361 elementsIDMap.clear(); 362 sidMap.clear(); 363 int i; 364 for (i=0;i<(int)documents.size();i++) 365 delete documents[i]; 366 documents.clear(); //this will free the daeElement 367 dae.getRawRefCache().clear(); 368 dae.getSidRefCache().clear(); 369 return DAE_OK; 370 } 371 372 daeUInt daeSTLDatabase::getElementCount(daeString name,daeString type,daeString file) 373 { 374 // If none of the search keys was specified, return the total element count in the database 375 if ( !name && !type && !file ) 376 { 377 daeUInt count = 0; 378 map< string, vector< daeElement*> >::iterator iter = elements.begin(); 379 map< string, vector< daeElement*> >::iterator end = elements.end(); 380 while( iter != end ) 381 { 382 count += (daeUInt)(*iter).second.size(); 383 ++iter; 384 } 385 return count; 386 } 387 388 if ( name ) 389 { 390 // name specified 391 int count = 0; 392 if ( file ) 393 { 394 // If a document URI was a search key (in file) resolve it to a text URI with no fragment 395 daeURI tempURI(dae, file,true); 396 daeDocument *col = getDocument( tempURI.getURI() ); 397 if ( col == NULL ) { 398 return 0; 399 } 400 // a document was specified 401 pair< multimap< string, daeElement* >::iterator, multimap< string, daeElement* >::iterator > range; 402 range = elementsIDMap.equal_range( string( name ) ); 403 multimap< string, daeElement* >::iterator i = range.first; 404 while ( i != range.second ) 405 { 406 if ( col == (*i).second->getDocument() ) 407 { 408 count++; 409 } 410 ++i; 411 } 412 return count; 413 } 414 else 415 { 416 //no file specified - just name 417 return (daeUInt)elementsIDMap.count( string( name ) ); 418 } 419 } 420 421 if ( type ) 422 { 423 // type specified 424 map< string, vector< daeElement*> >::iterator iter = elements.find( string( type ) ); 425 if ( iter == elements.end() ) 426 { 427 return 0; 428 } 429 430 int count = 0; 431 if ( file ) 432 { 433 // If a document URI was a search key (in file) resolve it to a text URI with no fragment 434 daeURI tempURI(dae, file,true); 435 daeDocument *col = getDocument( tempURI.getURI() ); 436 if ( col == NULL ) { 437 return 0; 438 } 439 // a document was specified 440 vector< daeElement* > &vec = (*iter).second; 441 vector< daeElement* >::iterator i = vec.begin(); 442 vector< daeElement* >::iterator end = vec.end(); 443 while( i != end ) 444 { 445 if ( col == (*i)->getDocument() ) 446 { 447 ++count; 448 } 449 ++i; 450 } 451 return count; 452 } 453 else 454 { 455 //no file specified - just type 456 return (daeUInt)(*iter).second.size(); 457 } 458 } 459 460 //if you get here only a file was specified 461 daeURI tempURI(dae, file,true); 462 daeDocument *col = getDocument( tempURI.getURI() ); 463 if ( col == NULL ) { 464 return 0; 465 } 466 //a document was specified 467 int count = 0; 468 map< string, vector< daeElement*> >::iterator iter = elements.begin(); 469 map< string, vector< daeElement*> >::iterator end = elements.end(); 470 while( iter != end ) 471 { 472 vector< daeElement* > &vec = (*iter).second; 473 vector< daeElement* >::iterator i = vec.begin(); 474 vector< daeElement* >::iterator end2 = vec.end(); 475 while( i != end2 ) 476 { 477 if( col == (*i)->getDocument() ) 478 { 479 ++count; 480 } 481 ++i; 482 } 483 ++iter; 484 } 485 return count; 486 487 } 488 489 daeInt daeSTLDatabase::getElement(daeElement** pElement,daeInt index,daeString name,daeString type,daeString file) 490 { 491 // If the index is out of range, there can be no match 492 if ( index < 0 ) 493 { 494 return DAE_ERR_QUERY_NO_MATCH; 495 } 496 497 // If no name, type or file was specified we return the element at "index" - SLOW 498 if ( !name && !type && !file ) 499 { 500 daeUInt count = 0; 501 map< string, vector< daeElement*> >::iterator iter = elements.begin(); 502 map< string, vector< daeElement*> >::iterator end = elements.end(); 503 while( iter != end ) 504 { 505 count += (daeUInt)(*iter).second.size(); 506 if ( (daeInt)count > index ) 507 { 508 *pElement = (*iter).second[index - (count - (*iter).second.size())] ; 509 return DAE_OK; 510 } 511 ++iter; 512 } 513 return DAE_ERR_QUERY_NO_MATCH; 514 } 515 516 if ( name ) 517 { 518 //name specified 519 int count = 0; 520 if ( file ) 521 { 522 // If a document URI was a search key (in file) resolve it to a text URI with no fragment 523 daeURI tempURI(dae, file, true); 524 daeDocument *col = getDocument( tempURI.getURI() ); 525 if ( col == NULL ) { 526 *pElement = NULL; 527 return DAE_ERR_QUERY_NO_MATCH; 528 } 529 //a document was specified 530 pair< multimap< string, daeElement* >::iterator, multimap< string, daeElement* >::iterator> range; 531 range = elementsIDMap.equal_range( string( name ) ); 532 multimap< string, daeElement* >::iterator i = range.first; 533 while ( i != range.second ) 534 { 535 if ( col == (*i).second->getDocument() ) 536 { 537 if ( count == index ) 538 { 539 *pElement = (*i).second; 540 return DAE_OK; 541 } 542 count++; 543 } 544 ++i; 545 } 546 *pElement = NULL; 547 return DAE_ERR_QUERY_NO_MATCH; 548 } 549 else 550 { 551 //no document specified 552 multimap< string, daeElement* >::iterator i = elementsIDMap.find( string( name ) ); 553 if ( index > (daeInt)elementsIDMap.count( string( name ) ) || i == elementsIDMap.end() ) 554 { 555 *pElement = NULL; 556 return DAE_ERR_QUERY_NO_MATCH; 557 } 558 for ( int x = 0; x < index; x++ ) 559 { 560 ++i; 561 } 562 *pElement = i->second; 563 return DAE_OK; 564 } 565 } 566 567 if ( type ) 568 { 569 map< string, vector< daeElement*> >::iterator iter = elements.find( string( type ) ); 570 if ( iter == elements.end() ) 571 { 572 *pElement = NULL; 573 return DAE_ERR_QUERY_NO_MATCH; 574 } 575 //type specified 576 int count = 0; 577 if ( file ) 578 { 579 // If a document URI was a search key (in file) resolve it to a text URI with no fragment 580 daeURI tempURI(dae, file, true); 581 daeDocument *col = getDocument( tempURI.getURI() ); 582 if ( col == NULL ) { 583 return DAE_ERR_QUERY_NO_MATCH; 584 } 585 //a document was specified 586 // a document was specified 587 vector< daeElement* > &vec = (*iter).second; 588 vector< daeElement* >::iterator i = vec.begin(); 589 vector< daeElement* >::iterator end = vec.end(); 590 while( i != end ) 591 { 592 if ( col == (*i)->getDocument() ) 593 { 594 if ( count == index ) 595 { 596 *pElement = (*i); 597 return DAE_OK; 598 } 599 ++count; 600 } 601 ++i; 602 } 603 return DAE_ERR_QUERY_NO_MATCH; 604 } 605 else 606 { 607 //no document specified 608 if ( index >= (daeInt)(*iter).second.size() ) 609 { 610 *pElement = NULL; 611 return DAE_ERR_QUERY_NO_MATCH; 612 } 613 *pElement = (*iter).second[index]; 614 return DAE_OK; 615 } 616 } 617 618 //if you get here only the file was specified - SLOW 619 daeURI tempURI(dae, file, true); 620 daeDocument *col = getDocument( tempURI.getURI() ); 621 if ( col == NULL ) { 622 return DAE_ERR_QUERY_NO_MATCH; 623 } 624 //a document was specified 625 int count = 0; 626 map< string, vector< daeElement*> >::iterator iter = elements.begin(); 627 map< string, vector< daeElement*> >::iterator end = elements.end(); 628 while( iter != end ) 629 { 630 vector< daeElement* > &vec = (*iter).second; 631 vector< daeElement* >::iterator i = vec.begin(); 632 vector< daeElement* >::iterator end2 = vec.end(); 633 while( i != end2 ) 634 { 635 if( col == (*i)->getDocument() ) 636 { 637 if( count == index ) 638 { 639 *pElement = (*i); 640 return DAE_OK; 641 } 642 ++count; 643 } 644 ++i; 645 } 646 ++iter; 647 } 648 return DAE_ERR_QUERY_NO_MATCH; 649 650 } 651 652 vector<daeElement*> daeSTLDatabase::idLookup(const string& id) { 653 vector<daeElement*> matchingElements; 654 idMapRange range = elementsIDMap.equal_range(id); 655 for (idMapIter iter = range.first; iter != range.second; iter++) 656 matchingElements.push_back(iter->second); 657 return matchingElements; 658 } 659 660 void daeSTLDatabase::typeLookup(daeInt typeID, 661 vector<daeElement*>& matchingElements, 662 daeDocument* doc) { 663 matchingElements.clear(); 664 typeMapRange range = typeMap.equal_range(typeID); 665 for (typeMapIter iter = range.first; iter != range.second; iter++) 666 if (!doc || doc == iter->second->getDocument()) 667 matchingElements.push_back(iter->second); 668 } 669 670 void daeSTLDatabase::sidLookup(const string& sid, 671 vector<daeElement*>& matchingElements, 672 daeDocument* doc) { 673 matchingElements.clear(); 674 if (!sid.empty()) { 675 sidMapRange range = sidMap.equal_range(sid); 676 for (sidMapIter iter = range.first; iter != range.second; iter++) 677 if (!doc || doc == iter->second->getDocument()) 678 matchingElements.push_back(iter->second); 679 } 680 } 681