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"
16 #include "osl/file.hxx"
17 #include "osl/mutex.hxx"
18 #include "rtl/ref.hxx"
19 #include "rtl/ustring.hxx"
20 #include "unoidl/unoidl.hxx"
22 #include "legacyprovider.hxx"
23 #include "sourcefileprovider.hxx"
24 #include "sourcetreeprovider.hxx"
25 #include "unoidlprovider.hxx"
31 class AggregatingModule
: public ModuleEntity
{
34 std::vector
< rtl::Reference
< Provider
> > const & providers
,
35 OUString
const & name
):
36 providers_(providers
), name_(name
)
40 virtual ~AggregatingModule() throw () {}
42 virtual std::vector
< OUString
> getMemberNames() const SAL_OVERRIDE
;
44 virtual rtl::Reference
< MapCursor
> createCursor() const SAL_OVERRIDE
;
46 std::vector
< rtl::Reference
< Provider
> > providers_
;
50 std::vector
< OUString
> AggregatingModule::getMemberNames() const {
51 std::set
< OUString
> names
;
52 for (std::vector
< rtl::Reference
< Provider
> >::const_iterator
i(
54 i
!= providers_
.end(); ++i
)
56 rtl::Reference
< Entity
> ent((*i
)->findEntity(name_
));
57 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
58 std::vector
< OUString
> ns(
59 static_cast< ModuleEntity
* >(ent
.get())->getMemberNames());
60 names
.insert(ns
.begin(), ns
.end());
63 return std::vector
< OUString
>(names
.begin(), names
.end());
66 class AggregatingCursor
: public MapCursor
{
69 std::vector
< rtl::Reference
< Provider
> > const & providers
,
70 OUString
const & name
):
71 providers_(providers
), name_(name
), iterator_(providers_
.begin())
75 virtual ~AggregatingCursor() throw () {}
77 virtual rtl::Reference
< Entity
> getNext(OUString
* name
) SAL_OVERRIDE
;
81 std::vector
< rtl::Reference
< Provider
> > providers_
;
83 std::vector
< rtl::Reference
< Provider
> >::iterator iterator_
;
84 rtl::Reference
< MapCursor
> cursor_
;
85 std::set
< OUString
> seen_
;
88 rtl::Reference
< Entity
> AggregatingCursor::getNext(OUString
* name
) {
89 while (cursor_
.is()) {
91 rtl::Reference
< Entity
> ent(cursor_
->getNext(&n
));
93 if (seen_
.insert(n
).second
) {
97 return ent
->getSort() == Entity::SORT_MODULE
98 ? new AggregatingModule(
99 providers_
, (name_
.isEmpty() ? name_
: name_
+ ".") + n
)
107 return rtl::Reference
< Entity
>();
110 void AggregatingCursor::findCursor() {
111 for (; !cursor_
.is() && iterator_
!= providers_
.end(); ++iterator_
) {
112 if (name_
.isEmpty()) {
113 cursor_
= (*iterator_
)->createRootCursor();
115 rtl::Reference
< Entity
> ent((*iterator_
)->findEntity(name_
));
116 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
117 cursor_
= static_cast< ModuleEntity
* >(ent
.get())->
124 rtl::Reference
< MapCursor
> AggregatingModule::createCursor() const {
125 return new AggregatingCursor(providers_
, name_
);
130 NoSuchFileException::~NoSuchFileException() throw () {}
132 FileFormatException::~FileFormatException() throw () {}
134 Entity::~Entity() throw () {}
136 MapCursor::~MapCursor() throw () {}
138 ModuleEntity::~ModuleEntity() throw () {}
140 PublishableEntity::~PublishableEntity() throw () {}
142 EnumTypeEntity::~EnumTypeEntity() throw () {}
144 PlainStructTypeEntity::~PlainStructTypeEntity() throw () {}
146 PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
150 ExceptionTypeEntity::~ExceptionTypeEntity() throw () {}
152 InterfaceTypeEntity::~InterfaceTypeEntity() throw () {}
154 TypedefEntity::~TypedefEntity() throw () {}
156 ConstantGroupEntity::~ConstantGroupEntity() throw () {}
158 SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() throw ()
161 AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() throw () {}
163 InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() throw () {}
165 ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() throw () {}
167 Provider::~Provider() throw () {}
169 rtl::Reference
< Provider
> Manager::addProvider(OUString
const & uri
) {
170 rtl::Reference
< Provider
> p(loadProvider(uri
));
173 osl::MutexGuard
g(mutex_
);
174 providers_
.push_back(p
);
179 rtl::Reference
< Entity
> Manager::findEntity(rtl::OUString
const & name
) const {
180 //TODO: caching? (here or in cppuhelper::TypeManager?)
181 osl::MutexGuard
g(mutex_
);
182 for (std::vector
< rtl::Reference
< Provider
> >::const_iterator
i(
184 i
!= providers_
.end(); ++i
)
186 rtl::Reference
< Entity
> ent((*i
)->findEntity(name
));
191 return rtl::Reference
< Entity
>();
194 rtl::Reference
< MapCursor
> Manager::createCursor(rtl::OUString
const & name
)
197 return new AggregatingCursor(providers_
, name
);
200 Manager::~Manager() throw () {}
202 rtl::Reference
< Provider
> Manager::loadProvider(OUString
const & uri
) {
203 osl::DirectoryItem item
;
204 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
205 osl::FileStatus
status(osl_FileStatus_Mask_Type
);
206 if (item
.getFileStatus(status
) == osl::FileBase::E_None
207 && status
.getFileType() == osl::FileStatus::Directory
)
209 return new detail::SourceTreeProvider(*this, uri
);
212 if (uri
.endsWith(".idl")) {
213 return new detail::SourceFileProvider(this, uri
);
216 return new detail::UnoidlProvider(uri
);
217 } catch (FileFormatException
& e
) {
220 "FileFormatException \"" << e
.getDetail() << "\", retrying <" << uri
221 << "> as legacy format");
222 return new detail::LegacyProvider(*this, uri
);
228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */