1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
11 #include <sal/log.hxx>
18 #include <osl/file.hxx>
19 #include <osl/mutex.hxx>
20 #include <rtl/ref.hxx>
21 #include <rtl/ustring.hxx>
22 #include <unoidl/unoidl.hxx>
24 #include "legacyprovider.hxx"
25 #include "sourcefileprovider.hxx"
26 #include "sourcetreeprovider.hxx"
27 #include "unoidlprovider.hxx"
33 class AggregatingModule
: public ModuleEntity
{
36 std::vector
< rtl::Reference
< Provider
> >&& providers
,
38 providers_(std::move(providers
)), name_(std::move(name
))
42 virtual ~AggregatingModule() noexcept override
{}
44 virtual std::vector
< OUString
> getMemberNames() const override
;
46 virtual rtl::Reference
< MapCursor
> createCursor() const override
;
48 std::vector
< rtl::Reference
< Provider
> > providers_
;
52 std::vector
< OUString
> AggregatingModule::getMemberNames() const {
53 std::set
< OUString
> names
;
54 for (auto & i
: providers_
) {
55 rtl::Reference
< Entity
> ent(i
->findEntity(name_
));
56 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
57 std::vector
< OUString
> ns(
58 static_cast< ModuleEntity
* >(ent
.get())->getMemberNames());
59 names
.insert(ns
.begin(), ns
.end());
62 return std::vector
< OUString
>(names
.begin(), names
.end());
65 class AggregatingCursor
: public MapCursor
{
68 std::vector
< rtl::Reference
< Provider
> >&& providers
,
70 providers_(std::move(providers
)), name_(std::move(name
)), iterator_(providers_
.begin())
74 virtual ~AggregatingCursor() noexcept override
{}
76 virtual rtl::Reference
< Entity
> getNext(OUString
* name
) override
;
80 std::vector
< rtl::Reference
< Provider
> > providers_
;
82 std::vector
< rtl::Reference
< Provider
> >::iterator iterator_
;
83 rtl::Reference
< MapCursor
> cursor_
;
84 std::set
< OUString
> seen_
;
87 rtl::Reference
< Entity
> AggregatingCursor::getNext(OUString
* name
) {
88 while (cursor_
.is()) {
90 rtl::Reference
< Entity
> ent(cursor_
->getNext(&n
));
92 if (seen_
.insert(n
).second
) {
93 if (name
!= nullptr) {
96 return ent
->getSort() == Entity::SORT_MODULE
97 ? new AggregatingModule(
98 std::vector(providers_
), (name_
.isEmpty() ? name_
: name_
+ ".") + n
)
106 return rtl::Reference
< Entity
>();
109 void AggregatingCursor::findCursor() {
110 for (; !cursor_
.is() && iterator_
!= providers_
.end(); ++iterator_
) {
111 if (name_
.isEmpty()) {
112 cursor_
= (*iterator_
)->createRootCursor();
114 rtl::Reference
< Entity
> ent((*iterator_
)->findEntity(name_
));
115 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
116 cursor_
= static_cast< ModuleEntity
* >(ent
.get())->
123 rtl::Reference
< MapCursor
> AggregatingModule::createCursor() const {
124 return new AggregatingCursor(std::vector(providers_
), name_
);
129 NoSuchFileException::~NoSuchFileException() noexcept
{}
131 FileFormatException::~FileFormatException() noexcept
{}
133 Entity::~Entity() noexcept
{}
135 MapCursor::~MapCursor() noexcept
{}
137 ModuleEntity::~ModuleEntity() noexcept
{}
139 PublishableEntity::~PublishableEntity() noexcept
{}
141 EnumTypeEntity::~EnumTypeEntity() noexcept
{}
143 PlainStructTypeEntity::~PlainStructTypeEntity() noexcept
{}
145 PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
149 ExceptionTypeEntity::~ExceptionTypeEntity() noexcept
{}
151 InterfaceTypeEntity::~InterfaceTypeEntity() noexcept
{}
153 TypedefEntity::~TypedefEntity() noexcept
{}
155 ConstantGroupEntity::~ConstantGroupEntity() noexcept
{}
157 SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() noexcept
160 AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() noexcept
{}
162 InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() noexcept
{}
164 ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() noexcept
{}
166 Provider::~Provider() noexcept
{}
168 rtl::Reference
< Provider
> Manager::addProvider(OUString
const & uri
) {
169 rtl::Reference
< Provider
> p(loadProvider(uri
));
172 osl::MutexGuard
g(mutex_
);
173 providers_
.push_back(p
);
178 rtl::Reference
< Entity
> Manager::findEntity(OUString
const & name
) const {
179 //TODO: caching? (here or in cppuhelper::TypeManager?)
180 osl::MutexGuard
g(mutex_
);
181 for (auto & i
: providers_
) {
182 rtl::Reference
< Entity
> ent(i
->findEntity(name
));
187 return rtl::Reference
< Entity
>();
190 rtl::Reference
< MapCursor
> Manager::createCursor(OUString
const & name
)
193 return new AggregatingCursor(std::vector(providers_
), name
);
196 Manager::~Manager() noexcept
{}
198 rtl::Reference
< Provider
> Manager::loadProvider(OUString
const & uri
) {
199 osl::DirectoryItem item
;
200 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
201 osl::FileStatus
status(osl_FileStatus_Mask_Type
);
202 if (item
.getFileStatus(status
) == osl::FileBase::E_None
203 && status
.getFileType() == osl::FileStatus::Directory
)
205 return new detail::SourceTreeProvider(*this, uri
);
208 if (uri
.endsWith(".idl")) {
209 return new detail::SourceFileProvider(this, uri
);
212 return new detail::UnoidlProvider(uri
);
213 } catch (FileFormatException
& e
) {
216 "FileFormatException \"" << e
.getDetail() << "\", retrying <" << uri
217 << "> as legacy format");
218 return new detail::LegacyProvider(*this, uri
);
224 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */