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 <dae.h>
10 #include <dae/daeDatabase.h>
11 #include <dae/daeDom.h>
12 #include <dae/daeIDRef.h>
13 #include <dae/daeMetaElement.h>
14 #include <modules/daeSTLDatabase.h>
15 #include <dae/daeErrorHandler.h>
16 #include <dae/daeRawResolver.h>
17 #include <dae/daeStandardURIResolver.h>
18 
19 #ifdef DOM_INCLUDE_LIBXML
20 #include <modules/daeLIBXMLPlugin.h>
21 #endif
22 
23 #ifdef DOM_INCLUDE_TINYXML
24 #include <dae/daeTinyXMLPlugin.h>
25 #endif
26 
27 using namespace std;
28 
29 // Don't include domConstants.h because it varies depending on the dom version,
30 
31 daeInt DAEInstanceCount = 0;
32 DAE::charEncoding DAE::globalCharEncoding = DAE::Utf8;
33 
34 void
cleanup()35 DAE::cleanup()
36 {
37     //Contributed by Nus - Wed, 08 Nov 2006
38     daeStringRef::releaseStringTable();
39     //----------------------
40 
41 #ifndef NO_BOOST
42     try
43     {
44         boost::filesystem::remove_all(cdom::getSafeTmpDir());
45     }
46     catch (...)
47     {
48         daeErrorHandler::get()->handleWarning("Could not remove temporary directory in DAE::cleanup()\n");
49     }
50 #endif
51 }
52 
init(daeDatabase * database_,daeIOPlugin * ioPlugin,const char * version)53 void DAE::init(daeDatabase* database_, daeIOPlugin* ioPlugin, const char* version) {
54     database = NULL;
55     plugin = NULL;
56     defaultDatabase = false;
57     defaultPlugin = false;
58 
59     metas.setCount(GetColladaTypeCount(version));
60     initializeDomMeta(*this,version);
61     COLLADA_VERSION = GetCOLLADA_VERSION(version);
62     COLLADA_NAMESPACE = GetCOLLADA_NAMESPACE(version);
63     DAEInstanceCount++;
64 
65     // The order of the URI resolvers is significant, so be careful
66     uriResolvers.list().append(new daeRawResolver(*this));
67     uriResolvers.list().append(new daeStandardURIResolver(*this));
68 
69     idRefResolvers.addResolver(new daeDefaultIDRefResolver(*this));
70 
71     setDatabase(database_);
72     setIOPlugin(ioPlugin);
73 }
74 
~DAE()75 DAE::~DAE()
76 {
77     if (defaultDatabase)
78         delete database;
79     if (defaultPlugin)
80         delete plugin;
81     if ( --DAEInstanceCount <= 0 )
82         cleanup();
83 }
84 
85 // Database setup
getDatabase()86 daeDatabase* DAE::getDatabase()
87 {
88     return database;
89 }
90 
setDatabase(daeDatabase * _database)91 daeInt DAE::setDatabase(daeDatabase* _database)
92 {
93     if (defaultDatabase)
94         delete database;
95     if (_database)
96     {
97         defaultDatabase = false;
98         database = _database;
99     }
100     else
101     {
102         //create default database
103         database = new daeSTLDatabase(*this);
104         defaultDatabase = true;
105     }
106     database->setMeta(getMeta(getDomCOLLADAID(COLLADA_VERSION)));
107     return DAE_OK;
108 }
109 
110 // IO Plugin setup
getIOPlugin()111 daeIOPlugin* DAE::getIOPlugin()
112 {
113     return plugin;
114 }
115 
setIOPlugin(daeIOPlugin * _plugin)116 daeInt DAE::setIOPlugin(daeIOPlugin* _plugin)
117 {
118     if (defaultPlugin)
119         delete plugin;
120     if (_plugin) {
121         defaultPlugin = false;
122         plugin = _plugin;
123     }
124     else {
125         plugin = NULL;
126         defaultPlugin = true;
127 
128         //create default plugin
129 #ifdef DOM_INCLUDE_LIBXML
130         plugin = new daeLIBXMLPlugin(*this);
131 #else
132 #ifdef DOM_INCLUDE_TINYXML
133         plugin = new daeTinyXMLPlugin;
134 #endif
135 #endif
136 
137         if (!plugin) {
138             daeErrorHandler::get()->handleWarning("No IOPlugin Set");
139             plugin = new daeIOEmpty;
140             return DAE_ERROR;
141         }
142     }
143 
144     int res = plugin->setMeta(getMeta(getDomCOLLADAID(COLLADA_VERSION)));
145     if (res != DAE_OK) {
146         if (defaultPlugin) {
147             defaultPlugin = false;
148             delete plugin;
149         }
150         plugin = NULL;
151     }
152     return res;
153 }
154 
155 
156 // Take a path (either a URI ref or a file system path) and return a full URI,
157 // using the current working directory as the base URI if a relative URI
158 // reference is given.
makeFullUri(const string & path)159 string DAE::makeFullUri(const string& path) {
160     daeURI uri(*this, cdom::nativePathToUri(path));
161     return uri.str();
162 }
163 
164 
add(const string & path)165 daeElement* DAE::add(const string& path) {
166     close(path);
167     string uri = makeFullUri(path);
168     database->insertDocument(uri.c_str());
169     return getRoot(uri);
170 }
171 
openCommon(const string & path,daeString buffer)172 domCOLLADAProxy* DAE::openCommon(const string& path, daeString buffer) {
173     close(path);
174     string uri = makeFullUri(path);
175     plugin->setDatabase(database);
176     if (plugin->read(daeURI(*this, uri.c_str()), buffer) != DAE_OK)
177         return NULL;
178     return getRoot(uri);
179 }
180 
open(const string & path)181 domCOLLADAProxy* DAE::open(const string& path) {
182     return openCommon(path, NULL);
183 }
184 
openFromMemory(const string & path,daeString buffer)185 domCOLLADAProxy* DAE::openFromMemory(const string& path, daeString buffer) {
186     return openCommon(path, buffer);
187 }
188 
writeCommon(const string & docPath,const string & pathToWriteTo,bool replace)189 bool DAE::writeCommon(const string& docPath, const string& pathToWriteTo, bool replace) {
190     string docUri = makeFullUri(docPath),
191            uriToWriteTo = makeFullUri(pathToWriteTo);
192     plugin->setDatabase(database);
193     if (daeDocument* doc = getDoc(docUri))
194         return plugin->write(daeURI(*this, uriToWriteTo.c_str()), doc, replace) == DAE_OK;
195     return false;
196 }
197 
write(const string & path)198 bool DAE::write(const string& path) {
199     return writeCommon(path, path, true);
200 }
201 
writeTo(const string & docPath,const string & pathToWriteTo)202 bool DAE::writeTo(const string& docPath, const string& pathToWriteTo) {
203     return writeCommon(docPath, pathToWriteTo, true);
204 }
205 
writeToMemory(const string & docPath,std::vector<char> & output)206 bool DAE::writeToMemory(const string& docPath, std::vector<char>& output)
207 {
208     string docUri = makeFullUri(docPath);
209     plugin->setDatabase(database);
210     if (daeDocument* doc = getDoc(docUri)) {
211         return plugin->writeToMemory(output, doc) == DAE_OK;
212     }
213     return false;
214 }
215 
writeAll()216 bool DAE::writeAll() {
217     for (int i = 0; i < getDocCount(); i++)
218         if (save((daeUInt)i, true) != DAE_OK)
219             return false;
220     return true;
221 }
222 
close(const string & path)223 void DAE::close(const string& path) {
224     database->removeDocument(getDoc(makeFullUri(path).c_str()));
225 }
226 
clear()227 daeInt DAE::clear() {
228     database->clear();
229     rawRefCache.clear();
230     sidRefCache.clear();
231     return DAE_OK;
232 }
233 
234 
235 // Deprecated methods
load(daeString uri,daeString docBuffer)236 daeInt DAE::load(daeString uri, daeString docBuffer) {
237     return openCommon(uri, docBuffer) ? DAE_OK : DAE_ERROR;
238 }
239 
save(daeString uri,daeBool replace)240 daeInt DAE::save(daeString uri, daeBool replace) {
241     return writeCommon(uri, uri, replace) ? DAE_OK : DAE_ERROR;
242 }
243 
save(daeUInt documentIndex,daeBool replace)244 daeInt DAE::save(daeUInt documentIndex, daeBool replace) {
245     if ((int)documentIndex >= getDocCount())
246         return DAE_ERROR;
247 
248     // Save it out to the URI it was loaded from
249     daeString uri = getDoc((int)documentIndex)->getDocumentURI()->getURI();
250     return writeCommon(uri, uri, replace) ? DAE_OK : DAE_ERROR;
251 }
252 
saveAs(daeString uriToSaveTo,daeString docUri,daeBool replace)253 daeInt DAE::saveAs(daeString uriToSaveTo, daeString docUri, daeBool replace) {
254     return writeCommon(docUri, uriToSaveTo, replace) ? DAE_OK : DAE_ERROR;
255 }
256 
saveAs(daeString uriToSaveTo,daeUInt documentIndex,daeBool replace)257 daeInt DAE::saveAs(daeString uriToSaveTo, daeUInt documentIndex, daeBool replace) {
258     if ((int)documentIndex >= getDocCount())
259         return DAE_ERROR;
260 
261     daeString docUri = getDoc((int)documentIndex)->getDocumentURI()->getURI();
262     return writeCommon(docUri, uriToSaveTo, replace) ? DAE_OK : DAE_ERROR;
263 }
264 
unload(daeString uri)265 daeInt DAE::unload(daeString uri) {
266     close(uri);
267     return DAE_OK;
268 }
269 
270 
getDocCount()271 int DAE::getDocCount() {
272     return (int)database->getDocumentCount();
273 }
274 
getDoc(int i)275 daeDocument* DAE::getDoc(int i) {
276     return database->getDocument(i);
277 }
278 
getDoc(const string & path)279 daeDocument* DAE::getDoc(const string& path) {
280     return database->getDocument(makeFullUri(path).c_str(), true);
281 }
282 
getRoot(const string & path)283 domCOLLADAProxy* DAE::getRoot(const string& path) {
284     if (daeDocument* doc = getDoc(path))
285         return (domCOLLADAProxy*)doc->getDomRoot();
286     return NULL;
287 }
288 
setRoot(const string & path,domCOLLADAProxy * root)289 bool DAE::setRoot(const string& path, domCOLLADAProxy* root) {
290     if (daeDocument* doc = getDoc(path))
291         doc->setDomRoot(root);
292     else
293         database->insertDocument(makeFullUri(path).c_str(), root);
294     return getRoot(path) != NULL;
295 }
296 
getDom(daeString uri)297 domCOLLADAProxy* DAE::getDom(daeString uri) {
298     return getRoot(uri);
299 }
300 
setDom(daeString uri,domCOLLADAProxy * dom)301 daeInt DAE::setDom(daeString uri, domCOLLADAProxy* dom) {
302     return setRoot(uri, dom);
303 }
304 
getDomVersion()305 daeString DAE::getDomVersion()
306 {
307     return(COLLADA_VERSION);
308 }
309 
getColladaNamespace()310 daeString DAE::getColladaNamespace()
311 {
312     return(COLLADA_NAMESPACE);
313 }
314 
getAtomicTypes()315 daeAtomicTypeList& DAE::getAtomicTypes() {
316     return atomicTypes;
317 }
318 
getMeta(daeInt typeID)319 daeMetaElement* DAE::getMeta(daeInt typeID) {
320     if (typeID < 0 || typeID >= daeInt(metas.getCount()))
321         return NULL;
322     return metas[typeID];
323 }
324 
getAllMetas()325 daeMetaElementRefArray& DAE::getAllMetas() {
326     return metas;
327 }
328 
setMeta(daeInt typeID,daeMetaElement & meta)329 void DAE::setMeta(daeInt typeID, daeMetaElement& meta) {
330     if (typeID < 0 || typeID >= daeInt(metas.getCount()))
331         return;
332     metas[typeID] = &meta;
333 }
334 
getURIResolvers()335 daeURIResolverList& DAE::getURIResolvers() {
336     return uriResolvers;
337 }
338 
getBaseURI()339 daeURI& DAE::getBaseURI() {
340     return baseUri;
341 }
342 
setBaseURI(const daeURI & uri)343 void DAE::setBaseURI(const daeURI& uri) {
344     baseUri = uri;
345 }
346 
setBaseURI(const string & uri)347 void DAE::setBaseURI(const string& uri) {
348     baseUri = uri.c_str();
349 }
350 
getIDRefResolvers()351 daeIDRefResolverList& DAE::getIDRefResolvers() {
352     return idRefResolvers;
353 }
354 
getRawRefCache()355 daeRawRefCache& DAE::getRawRefCache() {
356     return rawRefCache;
357 }
358 
getSidRefCache()359 daeSidRefCache& DAE::getSidRefCache() {
360     return sidRefCache;
361 }
362 
dummyFunction1()363 void DAE::dummyFunction1() {
364 }
365 
getGlobalCharEncoding()366 DAE::charEncoding DAE::getGlobalCharEncoding() {
367     return globalCharEncoding;
368 }
369 
setGlobalCharEncoding(charEncoding encoding)370 void DAE::setGlobalCharEncoding(charEncoding encoding) {
371     globalCharEncoding = encoding;
372 }
373 
getCharEncoding()374 DAE::charEncoding DAE::getCharEncoding() {
375     return localCharEncoding.get() ? *localCharEncoding : getGlobalCharEncoding();
376 }
377 
setCharEncoding(charEncoding encoding)378 void DAE::setCharEncoding(charEncoding encoding) {
379     localCharEncoding.reset(new charEncoding(encoding));
380 }
381