187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk/* 287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk* Copyright 2006 Sony Computer Entertainment Inc. 387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk* 487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk* Licensed under the MIT Open Source License, for details please see license.txt or the website 587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk* http://www.opensource.org/licenses/mit-license.php 687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk* 787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk*/ 887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <sstream> 1087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae.h> 1187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dom.h> 1287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae/daeDatabase.h> 1387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae/daeIOPluginCommon.h> 1487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae/daeMetaElement.h> 1587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae/daeErrorHandler.h> 1687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae/daeMetaElementAttribute.h> 1787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#ifndef NO_ZAE 1887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#include <dae/daeZAEUncompressHandler.h> 1987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#endif 2087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 2187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchoukusing namespace std; 2287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 2387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex SakhartchoukdaeIOPluginCommon::daeIOPluginCommon() 2487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk : database(NULL), 2587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk topMeta(NULL) 2687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk{ 2787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 2887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 2987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex SakhartchoukdaeIOPluginCommon::~daeIOPluginCommon() 3087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk{ 3187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 3287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 3387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex SakhartchoukdaeInt daeIOPluginCommon::setMeta(daeMetaElement *_topMeta) 3487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk{ 3587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk topMeta = _topMeta; 3687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_OK; 3787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 3887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 3987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchoukvoid daeIOPluginCommon::setDatabase(daeDatabase* _database) 4087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk{ 4187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk database = _database; 4287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 4387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 4487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk// This function needs to be re-entrant, it can be called recursively from inside of resolveAll 4587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk// to load files that the first file depends on. 4687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex SakhartchoukdaeInt daeIOPluginCommon::read(const daeURI& uri, daeString docBuffer) 4787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk{ 4887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // Make sure topMeta has been set before proceeding 4987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (topMeta == NULL) 5087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk { 5187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_ERR_BACKEND_IO; 5287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 5387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 5487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // Generate a version of the URI with the fragment removed 5587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeURI fileURI(*uri.getDAE(), uri.str(), true); 5687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 5787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk //check if document already exists 5887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if ( database->isDocumentLoaded( fileURI.getURI() ) ) 5987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk { 6087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_ERR_COLLECTION_ALREADY_EXISTS; 6187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 6287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 6387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeElementRef domObject = docBuffer ? 6487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk readFromMemory(docBuffer, fileURI) : 6587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk readFromFile(fileURI); // Load from URI 6687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 6787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#ifdef NO_ZAE 6887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 6987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (!domObject) { 7087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string msg = docBuffer ? 7187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk "Failed to load XML document from memory\n" : 7287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string("Failed to load ") + fileURI.str() + "\n"; 7387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleError(msg.c_str()); 7487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_ERR_BACKEND_IO; 7587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 7687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 7787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // Insert the document into the database, the Database will keep a ref on the main dom, so it won't get deleted 7887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // until we clear the database 7987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 8087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeDocument *document = NULL; 8187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 8287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk int res = database->insertDocument(fileURI.getURI(),domObject,&document); 8387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (res!= DAE_OK) 8487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return res; 8587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 8687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#else 8787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 8887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk bool zaeRoot = false; 8987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string extractedURI = ""; 9087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (!domObject) { 9187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeZAEUncompressHandler zaeHandler(fileURI); 9287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (zaeHandler.isZipFile()) 9387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk { 9487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string rootFilePath = zaeHandler.obtainRootFilePath(); 9587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeURI rootFileURI(*fileURI.getDAE(), rootFilePath); 9687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk domObject = readFromFile(rootFileURI); 9787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (!domObject) 9887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk { 9987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string msg = string("Failed to load ") + fileURI.str() + "\n"; 10087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleError(msg.c_str()); 10187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_ERR_BACKEND_IO; 10287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 10387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk zaeRoot = true; 10487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk extractedURI = rootFileURI.str(); 10587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 10687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk else 10787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk { 10887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string msg = docBuffer ? 10987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk "Failed to load XML document from memory\n" : 11087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk string("Failed to load ") + fileURI.str() + "\n"; 11187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleError(msg.c_str()); 11287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_ERR_BACKEND_IO; 11387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 11487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 11587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 11687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // Insert the document into the database, the Database will keep a ref on the main dom, so it won't get deleted 11787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // until we clear the database 11887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 11987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeDocument *document = NULL; 12087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 12187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk int res = database->insertDocument(fileURI.getURI(),domObject,&document, zaeRoot, extractedURI); 12287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (res!= DAE_OK) 12387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return res; 12487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 12587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk#endif 12687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 12787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return DAE_OK; 12887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 12987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 13987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex SakhartchoukdaeElementRef daeIOPluginCommon::beginReadElement(daeElement* parentElement, 14087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeString elementName, 14187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk const vector<attrPair>& attributes, 14287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeInt lineNumber) { 14387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeMetaElement* parentMeta = parentElement ? parentElement->getMeta() : topMeta; 14487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeElementRef element = parentMeta->create(elementName); 14587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 14687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if(!element) 14787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk { 14887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk ostringstream msg; 14987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk msg << "The DOM was unable to create an element named " << elementName << " at line " 15087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk << lineNumber << ". Probably a schema violation.\n"; 15187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleWarning( msg.str().c_str() ); 15287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return NULL; 15387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 15487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 15587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // Process the attributes 15687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk for (size_t i = 0; i < attributes.size(); i++) { 15787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeString name = attributes[i].first, 15887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk value = attributes[i].second; 15987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (!element->setAttribute(name, value)) { 16087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk ostringstream msg; 16187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk msg << "The DOM was unable to create an attribute " << name << " = " << value 16287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk << " at line " << lineNumber << ".\nProbably a schema violation.\n"; 16387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleWarning(msg.str().c_str()); 16487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 16587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 16687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 16787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (parentElement == NULL) { 16887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // This is the root element. Check the COLLADA version. 16987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeURI *xmlns = (daeURI*)(element->getMeta()->getMetaAttribute( "xmlns" )->getWritableMemory( element )); 17087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if ( strcmp( xmlns->getURI(), COLLADA_NAMESPACE ) != 0 ) { 17187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk // Invalid COLLADA version 17287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleError("Trying to load an invalid COLLADA version for this DOM build!"); 17387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return NULL; 17487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 17587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk } 17687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 17787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return element; 17887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 17987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 18087ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchoukbool daeIOPluginCommon::readElementText(daeElement* element, daeString text, daeInt elementLineNumber) { 18187ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk if (element->setCharData(text)) 18287ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return true; 18387ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk 18487ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk ostringstream msg; 18587ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk msg << "The DOM was unable to set a value for element of type " << element->getTypeName() 18687ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk << " at line " << elementLineNumber << ".\nProbably a schema violation.\n"; 18787ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk daeErrorHandler::get()->handleWarning(msg.str().c_str()); 18887ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk return false; 18987ac3e2db6d5ae163131102c066e9d19bdfdc139Alex Sakhartchouk} 190