void
CDA_CellMLElement::addEventListener
(
 const std::wstring& aType,
 iface::events::EventListener* aListener,
 bool aUseCapture
)
  throw(std::exception&)
{
  // Only bubbling is supported, as these events can't be cancelled.
  if (aUseCapture)
    throw iface::cellml_api::CellMLException(L"Only bubbling events are supported.");

  int32_t event = FindEventByName(aType);
  // Unknown events are silently ignored, as per the DOM Events specification.
  if (event == -1)
    return;

  // Find the adaptor, if there is one...
  ListenerToAdaptor_t::iterator i = mListenerToAdaptor.find(aListener);

  ObjRef<CDA_CellMLElementEventAdaptor> adaptor;

  if (i == mListenerToAdaptor.end())
  {
    // We add a refcount, putting the total to 2...
    adaptor = new CDA_CellMLElementEventAdaptor(this, aListener);
    // One refcount is used for the map, the other belongs to the ObjRef and
    // will be automatically dropped.
    mListenerToAdaptor.insert(std::pair<iface::events::EventListener*,
                              CDA_CellMLElementEventAdaptor*>
                              (aListener, adaptor)
                             );
  }
  else
    adaptor = (*i).second;

  try
  {
    adaptor->newEventType(event);
  }
  catch (std::exception& e)
  {
    adaptor->considerDestruction();
    throw e;
  }
}