Home | History | Annotate | Download | only in STLDatabase
      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