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