diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2013-10-24 09:48:13 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2013-10-24 09:57:09 +0200 |
commit | bdd55e28fc7788c2968daaf87b782f8e6189ee2d (patch) | |
tree | c69ba6b791bfed9aa2ec3dcd303ce1a29aa6613b /unoidl | |
parent | 32a001d85baf2b72a37b4ab8475f9489b7364769 (diff) |
fdo#67725 unoidl::AggregatingCursor must wrap modules for aggregation, too
Otherwise cppuhelper::TypeManager::createTypeDescriptionEnumeration, sitting on
top such an AggregatingCursor, will miss any entities from provider P' in module
M if any previous provider P contains the same module M.
That happened when climaker generates cli_oootypes.dll, where the enumeration
missed everything from offapi in top-level module "com" because it had already
seen udkapi's "com", and only reported the handful of entities under offapi's
other top-level module "org" (which does not appear in udkapi).
Change-Id: If538391bde22bcc346417b5988cf12023f0d4172
Diffstat (limited to 'unoidl')
-rw-r--r-- | unoidl/source/unoidl.cxx | 112 |
1 files changed, 78 insertions, 34 deletions
diff --git a/unoidl/source/unoidl.cxx b/unoidl/source/unoidl.cxx index 7c3e2e5bb7c5..6d716d46c4c3 100644 --- a/unoidl/source/unoidl.cxx +++ b/unoidl/source/unoidl.cxx @@ -28,41 +28,101 @@ namespace unoidl { namespace { +class AggregatingModule: public ModuleEntity { +public: + AggregatingModule( + std::vector< rtl::Reference< Provider > > const & providers, + OUString const & name): + providers_(providers), name_(name) + {} + +private: + virtual ~AggregatingModule() throw () {} + + virtual std::vector< OUString > getMemberNames() const; + + virtual rtl::Reference< MapCursor > createCursor() const; + + std::vector< rtl::Reference< Provider > > providers_; + OUString name_; +}; + +std::vector< OUString > AggregatingModule::getMemberNames() const { + std::set< OUString > names; + for (std::vector< rtl::Reference< Provider > >::const_iterator i( + providers_.begin()); + i != providers_.end(); ++i) + { + rtl::Reference< Entity > ent((*i)->findEntity(name_)); + if (ent.is() && ent->getSort() == Entity::SORT_MODULE) { + std::vector< OUString > ns( + static_cast< ModuleEntity * >(ent.get())->getMemberNames()); + names.insert(ns.begin(), ns.end()); + } + } + return std::vector< OUString >(names.begin(), names.end()); +} + class AggregatingCursor: public MapCursor { public: AggregatingCursor( - std::vector< rtl::Reference< MapCursor > > const & cursors): - cursors_(cursors), iterator_(cursors_.begin()) - {} + std::vector< rtl::Reference< Provider > > const & providers, + OUString const & name): + providers_(providers), name_(name), iterator_(providers_.begin()) + { findCursor(); } private: virtual ~AggregatingCursor() throw () {} - virtual rtl::Reference< Entity > getNext(rtl::OUString * name); + virtual rtl::Reference< Entity > getNext(OUString * name); - std::vector< rtl::Reference< MapCursor > > cursors_; - std::vector< rtl::Reference< MapCursor > >::iterator iterator_; - std::set< rtl::OUString > seenMembers; + void findCursor(); + + std::vector< rtl::Reference< Provider > > providers_; + OUString name_; + std::vector< rtl::Reference< Provider > >::iterator iterator_; + rtl::Reference< MapCursor > cursor_; + std::set< OUString > seen_; }; -rtl::Reference< Entity > AggregatingCursor::getNext(rtl::OUString * name) { - for (;;) { - if (iterator_ == cursors_.end()) { - return rtl::Reference< Entity >(); - } - rtl::OUString n; - rtl::Reference< Entity > ent((*iterator_)->getNext(&n)); +rtl::Reference< Entity > AggregatingCursor::getNext(OUString * name) { + while (cursor_.is()) { + OUString n; + rtl::Reference< Entity > ent(cursor_->getNext(&n)); if (ent.is()) { - if (seenMembers.insert(n).second) { + if (seen_.insert(n).second) { if (name != 0) { *name = n; } - return ent; + return ent->getSort() == Entity::SORT_MODULE + ? new AggregatingModule( + providers_, (name_.isEmpty() ? name_ : name_ + ".") + n) + : ent; } } else { - ++iterator_; + cursor_.clear(); + findCursor(); } } + return rtl::Reference< Entity >(); +} + +void AggregatingCursor::findCursor() { + for (; !cursor_.is() && iterator_ != providers_.end(); ++iterator_) { + if (name_.isEmpty()) { + cursor_ = (*iterator_)->createRootCursor(); + } else { + rtl::Reference< Entity > ent((*iterator_)->findEntity(name_)); + if (ent.is() && ent->getSort() == Entity::SORT_MODULE) { + cursor_ = static_cast< ModuleEntity * >(ent.get())-> + createCursor(); + } + } + } +} + +rtl::Reference< MapCursor > AggregatingModule::createCursor() const { + return new AggregatingCursor(providers_, name_); } } @@ -156,23 +216,7 @@ rtl::Reference< Entity > Manager::findEntity(rtl::OUString const & name) const { rtl::Reference< MapCursor > Manager::createCursor(rtl::OUString const & name) const { - std::vector< rtl::Reference< MapCursor > > curs; - for (std::vector< rtl::Reference< Provider > >::const_iterator i( - providers_.begin()); - i != providers_.end(); ++i) - { - if (name.isEmpty()) { - curs.push_back((*i)->createRootCursor()); - } else { - rtl::Reference< Entity > ent((*i)->findEntity(name)); - if (ent.is() && ent->getSort() == Entity::SORT_MODULE) { - curs.push_back( - static_cast< ModuleEntity * >(ent.get())->createCursor()); - } - } - } - return curs.empty() - ? rtl::Reference< MapCursor >() : new AggregatingCursor(curs); + return new AggregatingCursor(providers_, name); } Manager::~Manager() throw () {} |