/* * Copyright 2006 Sony Computer Entertainment Inc. * * Licensed under the MIT Open Source License, for details please see license.txt or the website * http://www.opensource.org/licenses/mit-license.php * */ #include #include using namespace std; daeSTLDatabase::daeSTLDatabase(DAE& dae) : daeDatabase(dae) { } daeSTLDatabase::~daeSTLDatabase() { clear(); } daeInt daeSTLDatabase::setMeta(daeMetaElement *_topMeta) { topMeta = _topMeta; return DAE_OK; } daeBool daeSTLDatabase::isDocumentLoaded(daeString name) { daeDocument* document = getDocument(name); if(document) return(true); else return(false); } // Element Types of all Elements daeUInt daeSTLDatabase::getTypeCount() { return (daeUInt)elements.size(); } daeString daeSTLDatabase::getTypeName(daeUInt index) { daeUInt count = 0; map >::iterator iter = elements.begin(); map >::iterator end = elements.end(); while ( iter != end ) { if ( count == index ) { return (*iter).first.c_str(); } ++count; ++iter; } return NULL; } // Documents daeInt daeSTLDatabase::insertDocument(const char *name, daeElement* dom, daeDocument** document, bool zaeRootDocument, const std::string& extractedFileURI) { return createDocument( name, dom, document, zaeRootDocument, extractedFileURI ); } daeInt daeSTLDatabase::createDocument(const char *name, daeElement* dom, daeDocument** document, bool zaeRootDocument, const std::string& extractedFileURI) { // If a document already exists with the same name, error if(isDocumentLoaded(name)) { if (document) *document = NULL; return DAE_ERR_COLLECTION_ALREADY_EXISTS; } // Make a new document daeDocument *newDocument = new daeDocument(dae, zaeRootDocument, extractedFileURI); newDocument->getDocumentURI()->setURI(name); newDocument->setDomRoot(dom); // Push the connection into the database documents.push_back(newDocument); if (document) *document = newDocument; return DAE_OK; } // !!!GAC revised version of insertDocument, creates a domCollada and fills it in for you. daeInt daeSTLDatabase::insertDocument(const char *name, daeDocument** document) { return createDocument( name, document ); } daeInt daeSTLDatabase::createDocument(const char *name, daeDocument** document) { // If a document already exists with the same name, error if(isDocumentLoaded(name)) { if (document) *document = NULL; return DAE_ERR_COLLECTION_ALREADY_EXISTS; } // Make the new document daeDocument *newDocument = new daeDocument(dae); // Make a domCOLLADA to be the root of this new document (this makes a reference so the domCOLLADA won't delete itself daeElementRef myCOLLADA = topMeta->create(); myCOLLADA->setDocument(newDocument); newDocument->getDocumentURI()->setURI(name); newDocument->setDomRoot(myCOLLADA); // Add this document to the list. documents.push_back(newDocument); // If the user gave us a place to put the document, send it back to them. if (document) *document = newDocument; return DAE_OK; } daeInt daeSTLDatabase::insertDocument( daeDocument *c ) { documents.push_back(c); insertElement( c, c->getDomRoot() ); return DAE_OK; } daeInt daeSTLDatabase::removeDocument(daeDocument *document) { vector< daeDocument* >::iterator iter = documents.begin(); while ( iter != documents.end() ) { if ( (*iter) == document ) { //delete all of its children removeElement( *iter, (*iter)->getDomRoot() ); delete *iter; // sthomas (see bug 1466019) iter = documents.erase(iter); } else { iter++; } } return DAE_OK; } daeUInt daeSTLDatabase::getDocumentCount() { return (daeUInt)documents.size(); } daeDocument* daeSTLDatabase::getDocument(daeUInt index) { if (indexgetDocumentURI()->str() == name) return(document); } return(NULL); } daeString daeSTLDatabase::getDocumentName(daeUInt index) { if (indexgetDocumentURI()->getURI(); else return NULL; } // Elements daeInt daeSTLDatabase::insertElement(daeDocument* document,daeElement* element) { insertChildren( document, element ); map >::iterator iter = elements.find( string( element->getTypeName() ) ); if ( iter != elements.end() ) { (*iter).second.push_back( element ); } else { vector< daeElement* > vec; vec.push_back( element ); elements.insert( make_pair( string( element->getTypeName() ), vec ) ); } // Insert into the type ID map typeMap.insert(make_pair(element->typeID(), element)); //insert into IDMap if element has an ID. IDMap is used to speed up URI resolution if ( element->getID() != NULL ) { elementsIDMap.insert( make_pair( string( element->getID() ), element ) ); } // Insert into sid map if the element has a sid // string sid = element->getAttribute("sid"); // if (!sid.empty()) // sidMap.insert(sidMapPair(sid, element)); dae.getSidRefCache().clear(); return DAE_OK; } daeInt daeSTLDatabase::insertChildren( daeDocument *c, daeElement *element ) { daeElementRefArray era; element->getChildren( era ); for ( unsigned int i = 0; i < era.getCount(); i++ ) { insertElement( c, era[i] ); } return DAE_OK; } daeInt daeSTLDatabase::removeElement(daeDocument* document,daeElement* element) { if ( !element ) { return DAE_ERR_INVALID_CALL; } removeChildren( document, element ); map >::iterator iter = elements.find( string( element->getTypeName() ) ); if ( iter != elements.end() ) { vector< daeElement* > &vec = (*iter).second; vector< daeElement* >::iterator i = vec.begin(); vector< daeElement* >::iterator end = vec.end(); while( i != end ) { if ( (*i) == element ) { vec.erase( i ); break; } ++i; } } typeMapRange range = typeMap.equal_range(element->typeID()); for (typeMapIter iter = range.first; iter != range.second; iter++) { if (iter->second == element) { typeMap.erase(iter); break; } } if ( element->getID() != NULL ) { idMapRange range = elementsIDMap.equal_range( string( element->getID() ) ); multimap::iterator iter = range.first; while( iter != range.second ) { if ( (*iter).second == element ) { elementsIDMap.erase( iter ); break; } ++iter; } } // string sid = element->getAttribute("sid"); // if (!sid.empty()) { // pair range = sidMap.equal_range(sid); // for (sidMapIter iter = range.first; iter != range.second; iter++) { // if (iter->second == element) { // sidMap.erase(iter); // break; // } // } // } dae.getSidRefCache().clear(); return DAE_OK; } daeInt daeSTLDatabase::removeChildren( daeDocument *c, daeElement *element ) { daeElementRefArray era; element->getChildren( era ); for ( unsigned int i = 0; i < era.getCount(); i++ ) { removeElement( c, era[i] ); } return DAE_OK; } daeInt daeSTLDatabase::changeElementID( daeElement* element, daeString newID ) { if ( !element ) { return DAE_ERR_INVALID_CALL; } // Remove the current entry in the ID map if the element has an ID if ( element->getID() != NULL ) { pair< multimap::iterator, multimap::iterator> range; range = elementsIDMap.equal_range( string( element->getID() ) ); multimap::iterator iter = range.first; while( iter != range.second ) { if ( (*iter).second == element ) { elementsIDMap.erase( iter ); break; } ++iter; } } // Add an entry to the ID map if the element will have an ID if ( newID != NULL ) { elementsIDMap.insert( make_pair( string( newID ), element ) ); } dae.getSidRefCache().clear(); return DAE_OK; } daeInt daeSTLDatabase::changeElementSID(daeElement* element, daeString newSID) { if (!element) return DAE_ERR_INVALID_CALL; // // Remove the current entry in the sid map if the element has a sid // string sid = element->getAttribute("sid"); // if (!sid.empty()) { // pair range = sidMap.equal_range(sid); // for (sidMapIter iter = range.first; iter != range.second; iter++) { // if (iter->second == element) { // sidMap.erase(iter); // break; // } // } // } // // Add an entry to the sid map if the element will have a sid // if ( newSID != NULL ) // sidMap.insert(sidMapPair(newSID, element)); dae.getSidRefCache().clear(); return DAE_OK; } daeInt daeSTLDatabase::clear() { elements.clear(); typeMap.clear(); elementsIDMap.clear(); sidMap.clear(); int i; for (i=0;i<(int)documents.size();i++) delete documents[i]; documents.clear(); //this will free the daeElement dae.getRawRefCache().clear(); dae.getSidRefCache().clear(); return DAE_OK; } daeUInt daeSTLDatabase::getElementCount(daeString name,daeString type,daeString file) { // If none of the search keys was specified, return the total element count in the database if ( !name && !type && !file ) { daeUInt count = 0; map< string, vector< daeElement*> >::iterator iter = elements.begin(); map< string, vector< daeElement*> >::iterator end = elements.end(); while( iter != end ) { count += (daeUInt)(*iter).second.size(); ++iter; } return count; } if ( name ) { // name specified int count = 0; if ( file ) { // If a document URI was a search key (in file) resolve it to a text URI with no fragment daeURI tempURI(dae, file,true); daeDocument *col = getDocument( tempURI.getURI() ); if ( col == NULL ) { return 0; } // a document was specified pair< multimap< string, daeElement* >::iterator, multimap< string, daeElement* >::iterator > range; range = elementsIDMap.equal_range( string( name ) ); multimap< string, daeElement* >::iterator i = range.first; while ( i != range.second ) { if ( col == (*i).second->getDocument() ) { count++; } ++i; } return count; } else { //no file specified - just name return (daeUInt)elementsIDMap.count( string( name ) ); } } if ( type ) { // type specified map< string, vector< daeElement*> >::iterator iter = elements.find( string( type ) ); if ( iter == elements.end() ) { return 0; } int count = 0; if ( file ) { // If a document URI was a search key (in file) resolve it to a text URI with no fragment daeURI tempURI(dae, file,true); daeDocument *col = getDocument( tempURI.getURI() ); if ( col == NULL ) { return 0; } // a document was specified vector< daeElement* > &vec = (*iter).second; vector< daeElement* >::iterator i = vec.begin(); vector< daeElement* >::iterator end = vec.end(); while( i != end ) { if ( col == (*i)->getDocument() ) { ++count; } ++i; } return count; } else { //no file specified - just type return (daeUInt)(*iter).second.size(); } } //if you get here only a file was specified daeURI tempURI(dae, file,true); daeDocument *col = getDocument( tempURI.getURI() ); if ( col == NULL ) { return 0; } //a document was specified int count = 0; map< string, vector< daeElement*> >::iterator iter = elements.begin(); map< string, vector< daeElement*> >::iterator end = elements.end(); while( iter != end ) { vector< daeElement* > &vec = (*iter).second; vector< daeElement* >::iterator i = vec.begin(); vector< daeElement* >::iterator end2 = vec.end(); while( i != end2 ) { if( col == (*i)->getDocument() ) { ++count; } ++i; } ++iter; } return count; } daeInt daeSTLDatabase::getElement(daeElement** pElement,daeInt index,daeString name,daeString type,daeString file) { // If the index is out of range, there can be no match if ( index < 0 ) { return DAE_ERR_QUERY_NO_MATCH; } // If no name, type or file was specified we return the element at "index" - SLOW if ( !name && !type && !file ) { daeUInt count = 0; map< string, vector< daeElement*> >::iterator iter = elements.begin(); map< string, vector< daeElement*> >::iterator end = elements.end(); while( iter != end ) { count += (daeUInt)(*iter).second.size(); if ( (daeInt)count > index ) { *pElement = (*iter).second[index - (count - (*iter).second.size())] ; return DAE_OK; } ++iter; } return DAE_ERR_QUERY_NO_MATCH; } if ( name ) { //name specified int count = 0; if ( file ) { // If a document URI was a search key (in file) resolve it to a text URI with no fragment daeURI tempURI(dae, file, true); daeDocument *col = getDocument( tempURI.getURI() ); if ( col == NULL ) { *pElement = NULL; return DAE_ERR_QUERY_NO_MATCH; } //a document was specified pair< multimap< string, daeElement* >::iterator, multimap< string, daeElement* >::iterator> range; range = elementsIDMap.equal_range( string( name ) ); multimap< string, daeElement* >::iterator i = range.first; while ( i != range.second ) { if ( col == (*i).second->getDocument() ) { if ( count == index ) { *pElement = (*i).second; return DAE_OK; } count++; } ++i; } *pElement = NULL; return DAE_ERR_QUERY_NO_MATCH; } else { //no document specified multimap< string, daeElement* >::iterator i = elementsIDMap.find( string( name ) ); if ( index > (daeInt)elementsIDMap.count( string( name ) ) || i == elementsIDMap.end() ) { *pElement = NULL; return DAE_ERR_QUERY_NO_MATCH; } for ( int x = 0; x < index; x++ ) { ++i; } *pElement = i->second; return DAE_OK; } } if ( type ) { map< string, vector< daeElement*> >::iterator iter = elements.find( string( type ) ); if ( iter == elements.end() ) { *pElement = NULL; return DAE_ERR_QUERY_NO_MATCH; } //type specified int count = 0; if ( file ) { // If a document URI was a search key (in file) resolve it to a text URI with no fragment daeURI tempURI(dae, file, true); daeDocument *col = getDocument( tempURI.getURI() ); if ( col == NULL ) { return DAE_ERR_QUERY_NO_MATCH; } //a document was specified // a document was specified vector< daeElement* > &vec = (*iter).second; vector< daeElement* >::iterator i = vec.begin(); vector< daeElement* >::iterator end = vec.end(); while( i != end ) { if ( col == (*i)->getDocument() ) { if ( count == index ) { *pElement = (*i); return DAE_OK; } ++count; } ++i; } return DAE_ERR_QUERY_NO_MATCH; } else { //no document specified if ( index >= (daeInt)(*iter).second.size() ) { *pElement = NULL; return DAE_ERR_QUERY_NO_MATCH; } *pElement = (*iter).second[index]; return DAE_OK; } } //if you get here only the file was specified - SLOW daeURI tempURI(dae, file, true); daeDocument *col = getDocument( tempURI.getURI() ); if ( col == NULL ) { return DAE_ERR_QUERY_NO_MATCH; } //a document was specified int count = 0; map< string, vector< daeElement*> >::iterator iter = elements.begin(); map< string, vector< daeElement*> >::iterator end = elements.end(); while( iter != end ) { vector< daeElement* > &vec = (*iter).second; vector< daeElement* >::iterator i = vec.begin(); vector< daeElement* >::iterator end2 = vec.end(); while( i != end2 ) { if( col == (*i)->getDocument() ) { if( count == index ) { *pElement = (*i); return DAE_OK; } ++count; } ++i; } ++iter; } return DAE_ERR_QUERY_NO_MATCH; } vector daeSTLDatabase::idLookup(const string& id) { vector matchingElements; idMapRange range = elementsIDMap.equal_range(id); for (idMapIter iter = range.first; iter != range.second; iter++) matchingElements.push_back(iter->second); return matchingElements; } void daeSTLDatabase::typeLookup(daeInt typeID, vector& matchingElements, daeDocument* doc) { matchingElements.clear(); typeMapRange range = typeMap.equal_range(typeID); for (typeMapIter iter = range.first; iter != range.second; iter++) if (!doc || doc == iter->second->getDocument()) matchingElements.push_back(iter->second); } void daeSTLDatabase::sidLookup(const string& sid, vector& matchingElements, daeDocument* doc) { matchingElements.clear(); if (!sid.empty()) { sidMapRange range = sidMap.equal_range(sid); for (sidMapIter iter = range.first; iter != range.second; iter++) if (!doc || doc == iter->second->getDocument()) matchingElements.push_back(iter->second); } }