PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/sources/cellml_context/CellMLContextImplementation.cpp

https://bitbucket.org/metatoaster/cellml-api
C++ | 1114 lines | 955 code | 115 blank | 44 comment | 162 complexity | 246624e9438f500af68a4fc1afda7c41 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-2.0
  1. #define IN_CELLMLCONTEXT_MODULE
  2. #include "CellMLContextImplementation.hxx"
  3. #include "CellMLContextBootstrap.hxx"
  4. #include "CellMLBootstrap.hpp"
  5. #include <locale>
  6. #include <sstream>
  7. #include <algorithm>
  8. // Win32 hack...
  9. #ifdef _WIN32
  10. #define swprintf _snwprintf
  11. #endif
  12. CDA_TypeAnnotationManager::~CDA_TypeAnnotationManager()
  13. {
  14. std::map<std::pair<std::wstring,std::wstring>, iface::XPCOM::IObject*>
  15. ::iterator i;
  16. for (i = annotations.begin(); i != annotations.end(); i++)
  17. {
  18. (*i).second->release_ref();
  19. }
  20. }
  21. void
  22. CDA_TypeAnnotationManager::setUserData(const wchar_t* type, const wchar_t* key,
  23. iface::XPCOM::IObject* data)
  24. throw(std::exception&)
  25. {
  26. std::pair<std::wstring,std::wstring> p(type, key);
  27. std::map<std::pair<std::wstring,std::wstring>, iface::XPCOM::IObject*>
  28. ::iterator i = annotations.find(p);
  29. if (i != annotations.end())
  30. {
  31. // If we can't release the reference, just drop it...
  32. (*i).second->release_ref();
  33. annotations.erase(i);
  34. }
  35. if (data == NULL)
  36. return;
  37. data->add_ref();
  38. annotations.insert(std::pair<std::pair<std::wstring,std::wstring>,
  39. iface::XPCOM::IObject*>(p, data));
  40. }
  41. iface::XPCOM::IObject*
  42. CDA_TypeAnnotationManager::getUserData(const wchar_t* type, const wchar_t* key)
  43. throw(std::exception&)
  44. {
  45. std::pair<std::wstring,std::wstring> p(type, key);
  46. std::map<std::pair<std::wstring,std::wstring>, iface::XPCOM::IObject*>
  47. ::iterator i = annotations.find(p);
  48. if (i == annotations.end())
  49. return NULL;
  50. (*i).second->add_ref();
  51. return (*i).second;
  52. }
  53. CDA_CellMLModuleIterator::CDA_CellMLModuleIterator
  54. (
  55. CDA_ModuleManager* aMM,
  56. std::list<iface::cellml_context::CellMLModule*>& aList
  57. )
  58. : _cda_refcount(1), mMM(aMM), mList(aList)
  59. {
  60. mMM->add_ref();
  61. mCurrent = mList.begin();
  62. mItIt = mMM->registerIterator(this);
  63. }
  64. CDA_CellMLModuleIterator::~CDA_CellMLModuleIterator()
  65. {
  66. mMM->deregisterIterator(mItIt);
  67. mMM->release_ref();
  68. }
  69. iface::cellml_context::CellMLModule*
  70. CDA_CellMLModuleIterator::nextModule()
  71. throw(std::exception&)
  72. {
  73. while (true)
  74. {
  75. if (mCurrent == mList.end())
  76. return NULL;
  77. iface::cellml_context::CellMLModule* ret = *mCurrent;
  78. ret->add_ref();
  79. mCurrent++;
  80. return ret;
  81. }
  82. }
  83. CDA_ModelNodeIterator::CDA_ModelNodeIterator
  84. (
  85. CDA_ModelList* aML,
  86. std::list<CDA_ModelNode*>& aList
  87. )
  88. : _cda_refcount(1), mML(aML), mList(aList)
  89. {
  90. mML->add_ref();
  91. mCurrent = mList.begin();
  92. mItIt = mML->registerIterator(this);
  93. }
  94. CDA_ModelNodeIterator::~CDA_ModelNodeIterator()
  95. {
  96. mML->deregisterIterator(mItIt);
  97. mML->release_ref();
  98. }
  99. iface::cellml_context::ModelNode*
  100. CDA_ModelNodeIterator::nextModelNode()
  101. throw(std::exception&)
  102. {
  103. if (mCurrent == mList.end())
  104. return NULL;
  105. iface::cellml_context::ModelNode* ret = *mCurrent;
  106. ret->add_ref();
  107. mCurrent++;
  108. return ret;
  109. }
  110. CDA_ModuleManager::CDA_ModuleManager()
  111. : _cda_refcount(1)
  112. {
  113. }
  114. CDA_ModuleManager::~CDA_ModuleManager()
  115. {
  116. std::list<iface::cellml_context::CellMLModuleMonitor*>::iterator i;
  117. for (i = mMonitors.begin(); i != mMonitors.end(); i++)
  118. {
  119. (*i)->release_ref();
  120. }
  121. std::list<iface::cellml_context::CellMLModule*>::iterator i2;
  122. for (i2 = mRegisteredModuleList.begin(); i2 != mRegisteredModuleList.end();
  123. i2++)
  124. {
  125. (*i2)->release_ref();
  126. }
  127. }
  128. void
  129. CDA_ModuleManager::registerModule
  130. (
  131. iface::cellml_context::CellMLModule* aModule
  132. )
  133. throw(std::exception&)
  134. {
  135. RETURN_INTO_WSTRING(mn, aModule->moduleName());
  136. RETURN_INTO_WSTRING(mv, aModule->moduleVersion());
  137. std::pair<std::wstring,std::wstring> nvp(mn, mv);
  138. // Ignore if already registered(is this right?)...
  139. if (mRegisteredModules.find(nvp) != mRegisteredModules.end())
  140. return;
  141. // If add_ref fails, so does registerModule, which is the correct behaviour.
  142. aModule->add_ref();
  143. mRegisteredModules.insert(std::pair<std::pair<std::wstring,std::wstring>,
  144. iface::cellml_context::CellMLModule*>
  145. (nvp, aModule));
  146. mRegisteredModuleList.push_back(aModule);
  147. std::list<iface::cellml_context::CellMLModuleMonitor*>::iterator i, j;
  148. for (i = mMonitors.begin(); i != mMonitors.end();)
  149. {
  150. j = i;
  151. i++;
  152. try
  153. {
  154. (*j)->moduleRegistered(aModule);
  155. }
  156. catch (...)
  157. {
  158. (*j)->release_ref();
  159. mMonitors.erase(j);
  160. }
  161. }
  162. }
  163. struct XPCOMEquator
  164. {
  165. // Warning: does *not* add_ref ao2, instead you must keep reference.
  166. XPCOMEquator(iface::XPCOM::IObject* ao2)
  167. {
  168. o2 = ao2;
  169. }
  170. bool
  171. operator()(
  172. iface::XPCOM::IObject* o1
  173. ) const
  174. {
  175. /* NULL != x unless x == NULL. */
  176. if (o1 == NULL)
  177. return o2 ? false : true;
  178. char *id1, *id2;
  179. id1 = o1->objid();
  180. id2 = o2->objid();
  181. bool ret = (strcmp(id1, id2) == 0);
  182. free(id1);
  183. free(id2);
  184. return ret;
  185. }
  186. private:
  187. iface::XPCOM::IObject* o2;
  188. };
  189. void
  190. CDA_ModuleManager::deregisterModule
  191. (
  192. iface::cellml_context::CellMLModule* aModule
  193. )
  194. throw(std::exception&)
  195. {
  196. RETURN_INTO_WSTRING(mn, aModule->moduleName());
  197. RETURN_INTO_WSTRING(mv, aModule->moduleVersion());
  198. std::map<std::pair<std::wstring,std::wstring>,
  199. iface::cellml_context::CellMLModule*>::iterator i;
  200. std::pair<std::wstring,std::wstring> nvp(mn, mv);
  201. i = mRegisteredModules.find(nvp);
  202. // Ignore if already registered(is this right?)...
  203. if (i == mRegisteredModules.end())
  204. return;
  205. XPCOMEquator xe(aModule);
  206. std::list<iface::cellml_context::CellMLModule*>::iterator i3
  207. = std::find_if(mRegisteredModuleList.begin(), mRegisteredModuleList.end(),
  208. xe);
  209. if (i3 == mRegisteredModuleList.end())
  210. return;
  211. std::list<iface::cellml_context::CellMLModuleMonitor*>::iterator i2, j2;
  212. for (i2 = mMonitors.begin(); i2 != mMonitors.end();)
  213. {
  214. j2 = i2;
  215. i2++;
  216. try
  217. {
  218. (*j2)->moduleDeregistered(aModule);
  219. }
  220. catch (...)
  221. {
  222. (*j2)->release_ref();
  223. mMonitors.erase(j2);
  224. }
  225. }
  226. std::list<CDA_CellMLModuleIterator*>::iterator i4;
  227. for (i4 = mIterators.begin(); i4 != mIterators.end(); i4++)
  228. (*i4)->invalidate(i3);
  229. mRegisteredModules.erase(i);
  230. (*i3)->release_ref();
  231. mRegisteredModuleList.erase(i3);
  232. }
  233. iface::cellml_context::CellMLModule*
  234. CDA_ModuleManager::findModuleByName
  235. (
  236. const wchar_t* moduleName, const wchar_t* moduleVersion
  237. )
  238. throw(std::exception&)
  239. {
  240. std::map<std::pair<std::wstring,std::wstring>,
  241. iface::cellml_context::CellMLModule*>::iterator i;
  242. std::pair<std::wstring,std::wstring> nvp(moduleName, moduleVersion);
  243. i = mRegisteredModules.find(nvp);
  244. if (i == mRegisteredModules.end())
  245. return NULL;
  246. (*i).second->add_ref();
  247. return (*i).second;
  248. }
  249. void
  250. CDA_ModuleManager::requestModuleByName
  251. (
  252. const wchar_t* moduleName, const wchar_t* moduleVersion
  253. )
  254. throw(std::exception&)
  255. {
  256. // This module manager currently doesn't support lazy loading.
  257. throw iface::cellml_api::CellMLException();
  258. }
  259. void
  260. CDA_ModuleManager::addMonitor
  261. (
  262. iface::cellml_context::CellMLModuleMonitor* aModuleMonitor
  263. )
  264. throw(std::exception&)
  265. {
  266. // If add_ref fails, so does the call (correct behaviour).
  267. aModuleMonitor->add_ref();
  268. mMonitors.push_back(aModuleMonitor);
  269. }
  270. void
  271. CDA_ModuleManager::removeMonitor
  272. (
  273. iface::cellml_context::CellMLModuleMonitor* aModuleMonitor
  274. )
  275. throw(std::exception&)
  276. {
  277. std::list<iface::cellml_context::CellMLModuleMonitor*>::iterator i;
  278. for (i = mMonitors.begin(); i != mMonitors.end(); i++)
  279. if (CDA_objcmp((*i), aModuleMonitor) == 0)
  280. {
  281. aModuleMonitor->release_ref();
  282. mMonitors.erase(i);
  283. return;
  284. }
  285. }
  286. iface::cellml_context::CellMLModuleIterator*
  287. CDA_ModuleManager::iterateModules()
  288. throw(std::exception&)
  289. {
  290. return new CDA_CellMLModuleIterator(this, mRegisteredModuleList);
  291. }
  292. CDA_ModelNode::CDA_ModelNode(iface::cellml_api::Model* aModel)
  293. : _cda_refcount(1), mIsFrozen(false), mParentList(NULL),
  294. mModelDirty(false)
  295. {
  296. // Scoped locale change.
  297. CNumericLocale locobj;
  298. // If add_ref fails, so does this call (correct behaviour).
  299. aModel->add_ref();
  300. mDerivedModels = new CDA_ModelList();
  301. mDerivedModels->mParentNode = this;
  302. mModel = aModel;
  303. installModelEventListener(mModel);
  304. // XXX threadsafety (but localtime_r isn't portable).
  305. // It would be nice to use C++ standard library locales for this, but it
  306. // doesn't work in enough places (e.g. not in Wine).
  307. time_t t = time(0);
  308. struct tm* lttm = localtime(&t);
  309. wchar_t buf[20];
  310. swprintf(buf, 20, L"%02u:%02u:%02u %04u-%02u-%02u",
  311. lttm->tm_hour, lttm->tm_min, lttm->tm_sec,
  312. lttm->tm_year + 1900, lttm->tm_mon + 1, lttm->tm_mday);
  313. mName = buf;
  314. stampModifiedNow();
  315. }
  316. CDA_ModelNode::~CDA_ModelNode()
  317. {
  318. // We need this or our reference count will go back to 1 and then down to 0
  319. // again in removeModelEventListener, triggering re-entrancy.
  320. add_ref();
  321. removeModelEventListener(mModel);
  322. mModel->release_ref();
  323. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i;
  324. for (i = mModelMonitors.begin(); i != mModelMonitors.end(); i++)
  325. {
  326. (*i)->release_ref();
  327. }
  328. delete mDerivedModels;
  329. }
  330. void
  331. CDA_ModelNode::add_ref()
  332. throw()
  333. {
  334. _cda_refcount++;
  335. if (mParentList)
  336. mParentList->add_ref();
  337. }
  338. void
  339. CDA_ModelNode::release_ref()
  340. throw()
  341. {
  342. _cda_refcount--;
  343. if (mParentList)
  344. mParentList->release_ref();
  345. else if (_cda_refcount == 0)
  346. delete this;
  347. }
  348. void
  349. CDA_ModelNode::name(const wchar_t* name)
  350. throw(std::exception&)
  351. {
  352. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, j;
  353. for (i = mModelMonitors.begin(); i != mModelMonitors.end();)
  354. {
  355. j = i;
  356. i++;
  357. try
  358. {
  359. (*j)->modelRenamed(this, name);
  360. }
  361. catch (...)
  362. {
  363. // Dead listeners get removed from the list...
  364. (*j)->release_ref();
  365. mModelMonitors.erase(j);
  366. }
  367. }
  368. // Now inform the ancestor lists...
  369. CDA_ModelList* curList = mParentList;
  370. while (curList)
  371. {
  372. for (i = curList->mNodeMonitors.begin(); i != curList->mNodeMonitors.end();)
  373. {
  374. j = i;
  375. i++;
  376. try
  377. {
  378. (*j)->modelRenamed(this, name);
  379. }
  380. catch (...)
  381. {
  382. // Dead listeners get removed from the list...
  383. (*j)->release_ref();
  384. curList->mNodeMonitors.erase(j);
  385. }
  386. }
  387. if (curList->mParentNode)
  388. curList = curList->mParentNode->mParentList;
  389. else
  390. curList = NULL;
  391. }
  392. mName = name;
  393. }
  394. wchar_t*
  395. CDA_ModelNode::name()
  396. throw(std::exception&)
  397. {
  398. return CDA_wcsdup(mName.c_str());
  399. }
  400. iface::cellml_context::ModelNode*
  401. CDA_ModelNode::getLatestDerivative()
  402. throw(std::exception&)
  403. {
  404. ObjRef<iface::cellml_context::ModelNode> bestCandidate = this;
  405. uint32_t bestStamp = mTimestamp;
  406. // Recurse into children...
  407. ObjRef<iface::cellml_context::ModelNodeIterator> mni =
  408. already_AddRefd<iface::cellml_context::ModelNodeIterator>
  409. (mDerivedModels->iterateModelNodes());
  410. while (true)
  411. {
  412. ObjRef<iface::cellml_context::ModelNode> mn =
  413. already_AddRefd<iface::cellml_context::ModelNode>(mni->nextModelNode());
  414. if (mn == NULL)
  415. break;
  416. ObjRef<iface::cellml_context::ModelNode> mnd =
  417. already_AddRefd<iface::cellml_context::ModelNode>
  418. (mn->getLatestDerivative());
  419. uint32_t newStamp = mnd->modificationTimestamp();
  420. if (newStamp > bestStamp)
  421. {
  422. bestStamp = newStamp;
  423. bestCandidate = mnd;
  424. }
  425. }
  426. bestCandidate->add_ref();
  427. return bestCandidate;
  428. }
  429. iface::cellml_context::ModelNode*
  430. CDA_ModelNode::getWritable()
  431. throw(std::exception&)
  432. {
  433. if (!mIsFrozen)
  434. {
  435. add_ref();
  436. return this;
  437. }
  438. // We are frozen, so need to clone model & make it a derivative...
  439. // There is no clone, so we abuse getAlternateVersion...
  440. RETURN_INTO_WSTRING(cv, mModel->cellmlVersion());
  441. ObjRef<iface::cellml_api::Model> modclone =
  442. already_AddRefd<iface::cellml_api::Model>(mModel->getAlternateVersion(cv.c_str()));
  443. if (modclone == NULL)
  444. throw iface::cellml_api::CellMLException();
  445. ObjRef<iface::cellml_context::ModelNode> cmn =
  446. already_AddRefd<iface::cellml_context::ModelNode>(new CDA_ModelNode
  447. (modclone));
  448. mDerivedModels->addModel(cmn);
  449. cmn->add_ref();
  450. return cmn;
  451. }
  452. bool
  453. CDA_ModelNode::isFrozen()
  454. throw(std::exception&)
  455. {
  456. return mIsFrozen;
  457. }
  458. void
  459. CDA_ModelNode::isFrozen(bool newState)
  460. throw(std::exception&)
  461. {
  462. if (mIsFrozen == newState)
  463. return;
  464. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, j;
  465. for (i = mModelMonitors.begin(); i != mModelMonitors.end();)
  466. {
  467. j = i;
  468. i++;
  469. try
  470. {
  471. (*j)->modelFrozenStateChanged(this, newState);
  472. }
  473. catch (...)
  474. {
  475. // Dead listeners get removed from the list...
  476. (*j)->release_ref();
  477. mModelMonitors.erase(j);
  478. }
  479. }
  480. // Now inform the ancestor lists...
  481. CDA_ModelList* curList = mParentList;
  482. while (curList)
  483. {
  484. for (i = curList->mNodeMonitors.begin(); i != curList->mNodeMonitors.end();)
  485. {
  486. j = i;
  487. i++;
  488. try
  489. {
  490. (*j)->modelFrozenStateChanged(this, newState);
  491. }
  492. catch (...)
  493. {
  494. // Dead listeners get removed from the list...
  495. (*j)->release_ref();
  496. curList->mNodeMonitors.erase(j);
  497. }
  498. }
  499. if (curList->mParentNode)
  500. curList = curList->mParentNode->mParentList;
  501. else
  502. curList = NULL;
  503. }
  504. mIsFrozen = newState;
  505. }
  506. uint32_t
  507. CDA_ModelNode::modificationTimestamp()
  508. throw(std::exception&)
  509. {
  510. return mTimestamp;
  511. }
  512. void
  513. CDA_ModelNode::stampModifiedNow()
  514. throw(std::exception&)
  515. {
  516. mTimestamp = time(0);
  517. }
  518. iface::cellml_api::Model*
  519. CDA_ModelNode::model()
  520. throw(std::exception&)
  521. {
  522. mModel->add_ref();
  523. return mModel;
  524. }
  525. void
  526. CDA_ModelNode::model(iface::cellml_api::Model* aModel)
  527. throw(std::exception&)
  528. {
  529. if (aModel == NULL)
  530. throw iface::cellml_api::CellMLException();
  531. removeModelEventListener(mModel);
  532. installModelEventListener(aModel);
  533. // Now notify the change...
  534. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, j;
  535. for (i = mModelMonitors.begin(); i != mModelMonitors.end();)
  536. {
  537. j = i;
  538. i++;
  539. try
  540. {
  541. (*j)->modelReplaced(this, aModel);
  542. }
  543. catch (...)
  544. {
  545. // Dead listeners get removed from the list...
  546. (*j)->release_ref();
  547. mModelMonitors.erase(j);
  548. }
  549. }
  550. // Now inform the ancestor lists...
  551. CDA_ModelList* curList = mParentList;
  552. while (curList)
  553. {
  554. for (i = curList->mNodeMonitors.begin(); i != curList->mNodeMonitors.end();)
  555. {
  556. j = i;
  557. i++;
  558. try
  559. {
  560. (*j)->modelReplaced(this, aModel);
  561. }
  562. catch (...)
  563. {
  564. // Dead listeners get removed from the list...
  565. (*j)->release_ref();
  566. curList->mNodeMonitors.erase(j);
  567. }
  568. }
  569. if (curList->mParentNode)
  570. curList = curList->mParentNode->mParentList;
  571. else
  572. curList = NULL;
  573. }
  574. if (CDA_objcmp(mModel, aModel))
  575. {
  576. mModel->release_ref();
  577. mModel = aModel;
  578. mModel->add_ref();
  579. }
  580. }
  581. void
  582. CDA_ModelNode::installModelEventListener(iface::cellml_api::Model* aModel)
  583. {
  584. DECLARE_QUERY_INTERFACE_OBJREF(m, aModel, cellml_api::CellMLDOMElement);
  585. if (m == NULL)
  586. return;
  587. RETURN_INTO_OBJREF(de, iface::dom::Element, m->domElement());
  588. if (de == NULL)
  589. return;
  590. RETURN_INTO_OBJREF(doc, iface::dom::Document, de->ownerDocument());
  591. if (doc == NULL)
  592. return;
  593. DECLARE_QUERY_INTERFACE_OBJREF(et, doc, events::EventTarget);
  594. et->addEventListener(L"DOMSubtreeModified", this, false);
  595. // Workaround for reference cycle: set refcount down by one after adding the
  596. // event listener. This means we will get deleted even while the event
  597. // listener still exists. We bump our own refcount up by one before removing
  598. // the event listener.
  599. release_ref();
  600. }
  601. void
  602. CDA_ModelNode::removeModelEventListener(iface::cellml_api::Model* aModel)
  603. {
  604. DECLARE_QUERY_INTERFACE_OBJREF(m, aModel, cellml_api::CellMLDOMElement);
  605. if (m == NULL)
  606. return;
  607. RETURN_INTO_OBJREF(de, iface::dom::Element, m->domElement());
  608. if (de == NULL)
  609. return;
  610. RETURN_INTO_OBJREF(doc, iface::dom::Document, de->ownerDocument());
  611. if (doc == NULL)
  612. return;
  613. DECLARE_QUERY_INTERFACE_OBJREF(et, doc, events::EventTarget);
  614. // Workaround for reference cycle: set refcount down by one after adding the
  615. // event listener, bump it back up before removing...
  616. add_ref();
  617. et->removeEventListener(L"DOMSubtreeModified", this, false);
  618. }
  619. void
  620. CDA_ModelNode::flushChanges()
  621. throw(std::exception&)
  622. {
  623. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, j;
  624. for (i = mModelMonitors.begin(); i != mModelMonitors.end();)
  625. {
  626. j = i;
  627. i++;
  628. try
  629. {
  630. (*j)->changesFlushed(this);
  631. }
  632. catch (...)
  633. {
  634. // Dead listeners get removed from the list...
  635. (*j)->release_ref();
  636. mModelMonitors.erase(j);
  637. }
  638. }
  639. // Now inform the ancestor lists...
  640. CDA_ModelList* curList = mParentList;
  641. while (curList)
  642. {
  643. for (i = curList->mNodeMonitors.begin(); i != curList->mNodeMonitors.end();)
  644. {
  645. j = i;
  646. i++;
  647. try
  648. {
  649. (*j)->changesFlushed(this);
  650. }
  651. catch (...)
  652. {
  653. // Dead listeners get removed from the list...
  654. (*j)->release_ref();
  655. curList->mNodeMonitors.erase(j);
  656. }
  657. }
  658. if (curList->mParentNode)
  659. curList = curList->mParentNode->mParentList;
  660. else
  661. curList = NULL;
  662. }
  663. }
  664. iface::XPCOM::IObject*
  665. CDA_ModelNode::owner()
  666. throw(std::exception&)
  667. {
  668. if (mOwner)
  669. mOwner->add_ref();
  670. return mOwner;
  671. }
  672. void
  673. CDA_ModelNode::owner(iface::XPCOM::IObject* aOwner)
  674. throw(std::exception&)
  675. {
  676. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, j;
  677. for (i = mModelMonitors.begin(); i != mModelMonitors.end();)
  678. {
  679. j = i;
  680. i++;
  681. try
  682. {
  683. (*j)->ownerChanged(this, aOwner);
  684. }
  685. catch (...)
  686. {
  687. // Dead listeners get removed from the list...
  688. (*j)->release_ref();
  689. mModelMonitors.erase(j);
  690. }
  691. }
  692. // Now inform the ancestor lists...
  693. CDA_ModelList* curList = mParentList;
  694. while (curList)
  695. {
  696. for (i = curList->mNodeMonitors.begin(); i != curList->mNodeMonitors.end();)
  697. {
  698. j = i;
  699. i++;
  700. try
  701. {
  702. (*j)->ownerChanged(this, aOwner);
  703. }
  704. catch (...)
  705. {
  706. // Dead listeners get removed from the list...
  707. (*j)->release_ref();
  708. curList->mNodeMonitors.erase(j);
  709. }
  710. }
  711. if (curList->mParentNode)
  712. curList = curList->mParentNode->mParentList;
  713. else
  714. curList = NULL;
  715. }
  716. mOwner = aOwner;
  717. }
  718. iface::cellml_context::ModelList*
  719. CDA_ModelNode::derivedModels()
  720. throw(std::exception&)
  721. {
  722. mDerivedModels->add_ref();
  723. return mDerivedModels;
  724. }
  725. void
  726. CDA_ModelNode::addModelMonitor
  727. (
  728. iface::cellml_context::ModelNodeMonitor* monitor
  729. )
  730. throw(std::exception&)
  731. {
  732. monitor->add_ref();
  733. mModelMonitors.push_back(monitor);
  734. }
  735. void
  736. CDA_ModelNode::removeModelMonitor
  737. (
  738. iface::cellml_context::ModelNodeMonitor* monitor
  739. )
  740. throw(std::exception&)
  741. {
  742. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, i2;
  743. for (i = mModelMonitors.begin(); i != mModelMonitors.end();)
  744. {
  745. i2 = i;
  746. i++;
  747. if (!CDA_objcmp(*i2, monitor))
  748. {
  749. (*i2)->release_ref();
  750. mModelMonitors.erase(i2);
  751. }
  752. }
  753. }
  754. iface::cellml_context::ModelList*
  755. CDA_ModelNode::parentList()
  756. throw(std::exception&)
  757. {
  758. if (mParentList == NULL)
  759. return NULL;
  760. mParentList->add_ref();
  761. return mParentList;
  762. }
  763. CDA_ModelList::CDA_ModelList()
  764. : _cda_refcount(1), mParentNode(NULL)
  765. {
  766. }
  767. CDA_ModelList::~CDA_ModelList()
  768. {
  769. std::list<CDA_ModelNode*>::iterator i;
  770. for (i = mModels.begin(); i != mModels.end(); i++)
  771. delete (*i);
  772. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i2;
  773. for (i2 = mNodeMonitors.begin(); i2 != mNodeMonitors.end(); i2++)
  774. (*i2)->release_ref();
  775. std::list<iface::cellml_context::ModelListMonitor*>::iterator i3;
  776. for (i3 = mListMonitors.begin(); i3 != mListMonitors.end(); i3++)
  777. (*i3)->release_ref();
  778. }
  779. void
  780. CDA_ModelList::add_ref()
  781. throw()
  782. {
  783. _cda_refcount++;
  784. if (mParentNode)
  785. mParentNode->add_ref();
  786. }
  787. void
  788. CDA_ModelList::release_ref()
  789. throw()
  790. {
  791. _cda_refcount--;
  792. if (mParentNode)
  793. mParentNode->release_ref();
  794. else if (_cda_refcount == 0)
  795. delete this;
  796. }
  797. void
  798. CDA_ModelList::addModelMonitor
  799. (
  800. iface::cellml_context::ModelNodeMonitor* monitor
  801. )
  802. throw(std::exception&)
  803. {
  804. monitor->add_ref();
  805. mNodeMonitors.push_back(monitor);
  806. }
  807. void
  808. CDA_ModelList::removeModelMonitor
  809. (
  810. iface::cellml_context::ModelNodeMonitor* monitor
  811. )
  812. throw(std::exception&)
  813. {
  814. std::list<iface::cellml_context::ModelNodeMonitor*>::iterator i, i2;
  815. for (i = mNodeMonitors.begin(); i != mNodeMonitors.end();)
  816. {
  817. i2 = i;
  818. i++;
  819. if (!CDA_objcmp(monitor, *i2))
  820. {
  821. (*i2)->release_ref();
  822. mNodeMonitors.erase(i2);
  823. }
  824. }
  825. }
  826. void
  827. CDA_ModelList::addListMonitor
  828. (
  829. iface::cellml_context::ModelListMonitor* monitor
  830. )
  831. throw(std::exception&)
  832. {
  833. monitor->add_ref();
  834. mListMonitors.push_back(monitor);
  835. }
  836. void
  837. CDA_ModelList::removeListMonitor
  838. (
  839. iface::cellml_context::ModelListMonitor* monitor
  840. )
  841. throw(std::exception&)
  842. {
  843. std::list<iface::cellml_context::ModelListMonitor*>::iterator i, i2;
  844. for (i = mListMonitors.begin(); i != mListMonitors.end();)
  845. {
  846. i2 = i;
  847. i++;
  848. (*i2)->release_ref();
  849. mListMonitors.erase(i2);
  850. }
  851. }
  852. iface::cellml_context::ModelNode*
  853. CDA_ModelList::makeNode(iface::cellml_api::Model* mod)
  854. throw(std::exception&)
  855. {
  856. if (mod == NULL)
  857. throw iface::cellml_api::CellMLException();
  858. return new CDA_ModelNode(mod);
  859. }
  860. void
  861. CDA_ModelList::addModel(iface::cellml_context::ModelNode* node)
  862. throw(std::exception&)
  863. {
  864. // Convert node...
  865. CDA_ModelNode* cnode = dynamic_cast<CDA_ModelNode*>(node);
  866. if (cnode == NULL)
  867. throw iface::cellml_api::CellMLException();
  868. if (cnode->mParentList != NULL)
  869. throw iface::cellml_api::CellMLException();
  870. cnode->setParentList(this);
  871. mModels.push_back(cnode);
  872. // Call the monitors back...
  873. std::list<iface::cellml_context::ModelListMonitor*>::iterator i;
  874. CDA_ModelList* curList = this;
  875. uint16_t depth = 0;
  876. while (curList)
  877. {
  878. for (i = curList->mListMonitors.begin(); i != curList->mListMonitors.end();
  879. i++)
  880. (*i)->modelAdded(node, depth);
  881. depth++;
  882. if (curList->mParentNode)
  883. curList = curList->mParentNode->mParentList;
  884. else
  885. curList = NULL;
  886. }
  887. }
  888. void
  889. CDA_ModelList::removeModel(iface::cellml_context::ModelNode* node)
  890. throw(std::exception&)
  891. {
  892. // Call the monitors back...
  893. std::list<iface::cellml_context::ModelListMonitor*>::iterator i;
  894. CDA_ModelList* curList = this;
  895. uint16_t depth = 0;
  896. while (curList)
  897. {
  898. for (i = curList->mListMonitors.begin(); i != curList->mListMonitors.end();
  899. i++)
  900. (*i)->modelRemoved(node, depth);
  901. depth++;
  902. if (curList->mParentNode)
  903. curList = curList->mParentNode->mParentList;
  904. else
  905. curList = NULL;
  906. }
  907. std::list<CDA_ModelNode*>::iterator i2, i3;
  908. for (i2 = mModels.begin(); i2 != mModels.end();)
  909. {
  910. i3 = i2;
  911. i2++;
  912. CDA_ModelNode* targ = *i3;
  913. if (targ != node)
  914. continue;
  915. targ->setParentList(NULL);
  916. std::list<CDA_ModelNodeIterator*>::iterator i4;
  917. for (i4 = mIterators.begin(); i4 != mIterators.end(); i4++)
  918. (*i4)->invalidate(i3);
  919. mModels.erase(i3);
  920. }
  921. }
  922. iface::cellml_context::ModelNodeIterator*
  923. CDA_ModelList::iterateModelNodes()
  924. throw(std::exception&)
  925. {
  926. return new CDA_ModelNodeIterator(this, mModels);
  927. }
  928. iface::cellml_context::ModelNode*
  929. CDA_ModelList::parentNode()
  930. throw(std::exception&)
  931. {
  932. if (mParentNode == NULL)
  933. return NULL;
  934. mParentNode->add_ref();
  935. return mParentNode;
  936. }
  937. void
  938. CDA_ModelNode::setParentList(CDA_ModelList* aParentList)
  939. {
  940. if (mParentList == aParentList)
  941. return;
  942. if (mParentList != NULL)
  943. {
  944. uint32_t i;
  945. for (i = 0; i < _cda_refcount; i++)
  946. mParentList->release_ref();
  947. }
  948. mParentList = aParentList;
  949. if (mParentList != NULL)
  950. {
  951. uint32_t i;
  952. for (i = 0; i < _cda_refcount; i++)
  953. mParentList->add_ref();
  954. }
  955. else if (_cda_refcount == 0)
  956. delete this;
  957. }
  958. void
  959. CDA_ModelNode::dirty(bool aDirty)
  960. throw(std::exception&)
  961. {
  962. mModelDirty = aDirty;
  963. }
  964. bool
  965. CDA_ModelNode::dirty()
  966. throw(std::exception&)
  967. {
  968. return mModelDirty;
  969. }
  970. void
  971. CDA_ModelNode::handleEvent(iface::events::Event* aEvent)
  972. throw(std::exception&)
  973. {
  974. mModelDirty = true;
  975. }
  976. CDA_CellMLContext::CDA_CellMLContext()
  977. : _cda_refcount(1)
  978. {
  979. mModuleManager = new CDA_ModuleManager();
  980. mTypeAnnotationManager = new CDA_TypeAnnotationManager();
  981. mCellMLBootstrap = CreateCellMLBootstrap();
  982. mModelList = new CDA_ModelList();
  983. }
  984. CDA_CellMLContext::~CDA_CellMLContext()
  985. {
  986. if (mModuleManager != NULL)
  987. mModuleManager->release_ref();
  988. if (mTypeAnnotationManager != NULL)
  989. mTypeAnnotationManager->release_ref();
  990. if (mCellMLBootstrap != NULL)
  991. mCellMLBootstrap->release_ref();
  992. if (mModelList != NULL)
  993. mModelList->release_ref();
  994. }
  995. CDA_EXPORT_PRE CDA_EXPORT_POST iface::cellml_context::CellMLContext*
  996. CreateCellMLContext()
  997. {
  998. return new CDA_CellMLContext();
  999. }