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
This commit is contained in:
@@ -28,41 +28,101 @@ namespace unoidl {
|
|||||||
|
|
||||||
namespace {
|
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 {
|
class AggregatingCursor: public MapCursor {
|
||||||
public:
|
public:
|
||||||
AggregatingCursor(
|
AggregatingCursor(
|
||||||
std::vector< rtl::Reference< MapCursor > > const & cursors):
|
std::vector< rtl::Reference< Provider > > const & providers,
|
||||||
cursors_(cursors), iterator_(cursors_.begin())
|
OUString const & name):
|
||||||
{}
|
providers_(providers), name_(name), iterator_(providers_.begin())
|
||||||
|
{ findCursor(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~AggregatingCursor() throw () {}
|
virtual ~AggregatingCursor() throw () {}
|
||||||
|
|
||||||
virtual rtl::Reference< Entity > getNext(rtl::OUString * name);
|
virtual rtl::Reference< Entity > getNext(OUString * name);
|
||||||
|
|
||||||
std::vector< rtl::Reference< MapCursor > > cursors_;
|
void findCursor();
|
||||||
std::vector< rtl::Reference< MapCursor > >::iterator iterator_;
|
|
||||||
std::set< rtl::OUString > seenMembers;
|
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) {
|
rtl::Reference< Entity > AggregatingCursor::getNext(OUString * name) {
|
||||||
for (;;) {
|
while (cursor_.is()) {
|
||||||
if (iterator_ == cursors_.end()) {
|
OUString n;
|
||||||
return rtl::Reference< Entity >();
|
rtl::Reference< Entity > ent(cursor_->getNext(&n));
|
||||||
}
|
|
||||||
rtl::OUString n;
|
|
||||||
rtl::Reference< Entity > ent((*iterator_)->getNext(&n));
|
|
||||||
if (ent.is()) {
|
if (ent.is()) {
|
||||||
if (seenMembers.insert(n).second) {
|
if (seen_.insert(n).second) {
|
||||||
if (name != 0) {
|
if (name != 0) {
|
||||||
*name = n;
|
*name = n;
|
||||||
}
|
}
|
||||||
return ent;
|
return ent->getSort() == Entity::SORT_MODULE
|
||||||
|
? new AggregatingModule(
|
||||||
|
providers_, (name_.isEmpty() ? name_ : name_ + ".") + n)
|
||||||
|
: ent;
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
rtl::Reference< MapCursor > Manager::createCursor(rtl::OUString const & name)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
std::vector< rtl::Reference< MapCursor > > curs;
|
return new AggregatingCursor(providers_, name);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager() throw () {}
|
Manager::~Manager() throw () {}
|
||||||
|
Reference in New Issue
Block a user