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