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 <sstream>
10#include <dae.h>
11#include <dom.h>
12#include <dae/daeDatabase.h>
13#include <dae/daeIOPluginCommon.h>
14#include <dae/daeMetaElement.h>
15#include <dae/daeErrorHandler.h>
16#include <dae/daeMetaElementAttribute.h>
17#ifndef NO_ZAE
18#include <dae/daeZAEUncompressHandler.h>
19#endif
20
21using namespace std;
22
23daeIOPluginCommon::daeIOPluginCommon()
24	: database(NULL),
25		topMeta(NULL)
26{
27}
28
29daeIOPluginCommon::~daeIOPluginCommon()
30{
31}
32
33daeInt daeIOPluginCommon::setMeta(daeMetaElement *_topMeta)
34{
35	topMeta = _topMeta;
36	return DAE_OK;
37}
38
39void daeIOPluginCommon::setDatabase(daeDatabase* _database)
40{
41	database = _database;
42}
43
44// This function needs to be re-entrant, it can be called recursively from inside of resolveAll
45// to load files that the first file depends on.
46daeInt daeIOPluginCommon::read(const daeURI& uri, daeString docBuffer)
47{
48	// Make sure topMeta has been set before proceeding
49	if (topMeta == NULL)
50	{
51		return DAE_ERR_BACKEND_IO;
52	}
53
54	// Generate a version of the URI with the fragment removed
55	daeURI fileURI(*uri.getDAE(), uri.str(), true);
56
57	//check if document already exists
58	if ( database->isDocumentLoaded( fileURI.getURI() ) )
59	{
60		return DAE_ERR_COLLECTION_ALREADY_EXISTS;
61	}
62
63     daeElementRef domObject = docBuffer ?
64            readFromMemory(docBuffer, fileURI) :
65            readFromFile(fileURI); // Load from URI
66
67#ifdef NO_ZAE
68
69	if (!domObject) {
70		string msg = docBuffer ?
71			"Failed to load XML document from memory\n" :
72			string("Failed to load ") + fileURI.str() + "\n";
73		daeErrorHandler::get()->handleError(msg.c_str());
74		return DAE_ERR_BACKEND_IO;
75	}
76
77	// Insert the document into the database, the Database will keep a ref on the main dom, so it won't get deleted
78	// until we clear the database
79
80	daeDocument *document = NULL;
81
82	int res = database->insertDocument(fileURI.getURI(),domObject,&document);
83	if (res!= DAE_OK)
84		return res;
85
86#else
87
88    bool zaeRoot = false;
89    string extractedURI = "";
90    if (!domObject) {
91        daeZAEUncompressHandler zaeHandler(fileURI);
92        if (zaeHandler.isZipFile())
93        {
94            string rootFilePath = zaeHandler.obtainRootFilePath();
95            daeURI rootFileURI(*fileURI.getDAE(), rootFilePath);
96            domObject = readFromFile(rootFileURI);
97            if (!domObject)
98            {
99                string msg = string("Failed to load ") + fileURI.str() + "\n";
100                daeErrorHandler::get()->handleError(msg.c_str());
101                return DAE_ERR_BACKEND_IO;
102            }
103            zaeRoot = true;
104            extractedURI = rootFileURI.str();
105        }
106        else
107        {
108            string msg = docBuffer ?
109                "Failed to load XML document from memory\n" :
110            string("Failed to load ") + fileURI.str() + "\n";
111            daeErrorHandler::get()->handleError(msg.c_str());
112            return DAE_ERR_BACKEND_IO;
113        }
114    }
115
116    // Insert the document into the database, the Database will keep a ref on the main dom, so it won't get deleted
117    // until we clear the database
118
119    daeDocument *document = NULL;
120
121    int res = database->insertDocument(fileURI.getURI(),domObject,&document, zaeRoot, extractedURI);
122    if (res!= DAE_OK)
123        return res;
124
125#endif
126
127	return DAE_OK;
128}
129
130
131
132
133
134
135
136
137
138
139daeElementRef daeIOPluginCommon::beginReadElement(daeElement* parentElement,
140																									daeString elementName,
141																									const vector<attrPair>& attributes,
142																									daeInt lineNumber) {
143	daeMetaElement* parentMeta = parentElement ? parentElement->getMeta() : topMeta;
144	daeElementRef element = parentMeta->create(elementName);
145
146	if(!element)
147	{
148		ostringstream msg;
149		msg << "The DOM was unable to create an element named " << elementName << " at line "
150			     << lineNumber << ". Probably a schema violation.\n";
151		daeErrorHandler::get()->handleWarning( msg.str().c_str() );
152		return NULL;
153	}
154
155	// Process the attributes
156	for (size_t i = 0; i < attributes.size(); i++) {
157		daeString name  = attributes[i].first,
158			        value = attributes[i].second;
159		if (!element->setAttribute(name, value)) {
160			ostringstream msg;
161			msg << "The DOM was unable to create an attribute " << name << " = " << value
162				  << " at line " << lineNumber << ".\nProbably a schema violation.\n";
163			daeErrorHandler::get()->handleWarning(msg.str().c_str());
164		}
165	}
166
167	if (parentElement == NULL) {
168		// This is the root element. Check the COLLADA version.
169		daeURI *xmlns = (daeURI*)(element->getMeta()->getMetaAttribute( "xmlns" )->getWritableMemory( element ));
170		if ( strcmp( xmlns->getURI(), COLLADA_NAMESPACE ) != 0 ) {
171			// Invalid COLLADA version
172			daeErrorHandler::get()->handleError("Trying to load an invalid COLLADA version for this DOM build!");
173			return NULL;
174		}
175	}
176
177	return element;
178}
179
180bool daeIOPluginCommon::readElementText(daeElement* element, daeString text, daeInt elementLineNumber) {
181	if (element->setCharData(text))
182		return true;
183
184	ostringstream msg;
185	msg << "The DOM was unable to set a value for element of type " << element->getTypeName()
186			<< " at line " << elementLineNumber << ".\nProbably a schema violation.\n";
187	daeErrorHandler::get()->handleWarning(msg.str().c_str());
188	return false;
189}
190