LibreOffice Module filter (master) 1
basecontainer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include "basecontainer.hxx"
22
23#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
24#include <com/sun/star/uno/Type.h>
28#include <osl/diagnose.h>
29
31
33 : m_eType()
34{
36}
37
38
40{
41}
42
43
44void BaseContainer::init(const OUString& sImplementationName,
45 const css::uno::Sequence< OUString >& lServiceNames ,
47{
48 // SAFE ->
49 std::unique_lock aLock(m_aMutex);
50
52 m_lServiceNames = lServiceNames ;
53 m_eType = eType ;
54 // <- SAFE
55}
56
57
58void BaseContainer::impl_loadOnDemand(std::unique_lock<std::mutex>& /*rGuard*/)
59{
60 // A generic container needs all items of a set of our cache!
61 // Of course it can block for a while, till the cache is really filled.
62 // Note: don't load all sets supported by the cache here!
63
65 switch(m_eType)
66 {
68 eRequiredState = FilterCache::E_CONTAINS_TYPES;
69 break;
70
72 eRequiredState = FilterCache::E_CONTAINS_FILTERS;
73 break;
74
77 break;
78
81 break;
82 }
83
84 GetTheFilterCache().load(eRequiredState);
85}
86
87
88void BaseContainer::impl_initFlushMode(std::unique_lock<std::mutex>& /*rGuard*/)
89{
90 if (!m_pFlushCache)
92 if (!m_pFlushCache)
93 throw css::uno::RuntimeException( "Can not create write copy of internal used cache on demand.",
94 getXWeak());
95}
96
97
98FilterCache* BaseContainer::impl_getWorkingCache(std::unique_lock<std::mutex>& /*rGuard*/) const
99{
100 if (m_pFlushCache)
101 return m_pFlushCache.get();
102 else
103 return &GetTheFilterCache();
104}
105
106
108{
110}
111
112
113sal_Bool SAL_CALL BaseContainer::supportsService(const OUString& sServiceName)
114{
116}
117
118css::uno::Sequence< OUString > SAL_CALL BaseContainer::getSupportedServiceNames()
119{
120 return m_lServiceNames;
121}
122
123
124void SAL_CALL BaseContainer::insertByName(const OUString& sItem ,
125 const css::uno::Any& aValue)
126{
127 if (sItem.isEmpty())
128 throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
129 static_cast< css::container::XNameContainer* >(this),
130 1);
131
132 CacheItem aItem;
133 try
134 {
135 aItem << aValue;
136 }
137 catch(const css::uno::Exception& ex)
138 {
139 throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
140 }
141
142 // SAFE -> ----------------------------------
143 std::unique_lock aLock(m_aMutex);
144
145 impl_loadOnDemand(aLock);
146
147 // create write copy of used cache on demand ...
148 impl_initFlushMode(aLock);
149
150 FilterCache* pCache = impl_getWorkingCache(aLock);
151 if (pCache->hasItem(m_eType, sItem))
152 throw css::container::ElementExistException(OUString(), static_cast< css::container::XNameContainer* >(this));
153 pCache->setItem(m_eType, sItem, aItem);
154 // <- SAFE ----------------------------------
155}
156
157
158void SAL_CALL BaseContainer::removeByName(const OUString& sItem)
159{
160 // SAFE -> ----------------------------------
161 std::unique_lock aLock(m_aMutex);
162
163 impl_loadOnDemand(aLock);
164
165 // create write copy of used cache on demand ...
166 impl_initFlushMode(aLock);
167
168 FilterCache* pCache = impl_getWorkingCache(aLock);
169 pCache->removeItem(m_eType, sItem); // throw exceptions automatically
170 // <- SAFE ----------------------------------
171}
172
173
174void SAL_CALL BaseContainer::replaceByName(const OUString& sItem ,
175 const css::uno::Any& aValue)
176{
177 if (sItem.isEmpty())
178 throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
179 static_cast< css::container::XNameContainer* >(this),
180 1);
181
182 CacheItem aItem;
183 try
184 {
185 aItem << aValue;
186 }
187 catch(const css::uno::Exception& ex)
188 {
189 throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
190 }
191
192 // SAFE -> ----------------------------------
193 std::unique_lock aLock(m_aMutex);
194
195 impl_loadOnDemand(aLock);
196
197 // create write copy of used cache on demand ...
198 impl_initFlushMode(aLock);
199
200 FilterCache* pCache = impl_getWorkingCache(aLock);
201 if (!pCache->hasItem(m_eType, sItem))
202 throw css::container::NoSuchElementException(OUString(), static_cast< css::container::XNameContainer* >(this));
203 pCache->setItem(m_eType, sItem, aItem);
204 // <- SAFE ----------------------------------
205}
206
207
208css::uno::Any SAL_CALL BaseContainer::getByName(const OUString& sItem)
209{
210 if (sItem.isEmpty())
211 throw css::container::NoSuchElementException( "An empty item can't be part of this cache!",
212 static_cast< css::container::XNameAccess* >(this));
213
214 css::uno::Any aValue;
215
216 // SAFE ->
217 std::unique_lock aLock(m_aMutex);
218
219 impl_loadOnDemand(aLock);
220
221 try
222 {
223 FilterCache* pCache = impl_getWorkingCache(aLock);
224 aValue = pCache->getItemWithStateProps(m_eType, sItem);
225 }
226 catch(const css::container::NoSuchElementException&)
227 {
228 throw;
229 }
230 catch(const css::uno::Exception&)
231 {
232 // TODO invalid cache!? How should it be handled right?
233 }
234
235 // <- SAFE
236
237 return aValue;
238}
239
240
241css::uno::Sequence< OUString > SAL_CALL BaseContainer::getElementNames()
242{
243 css::uno::Sequence< OUString > lNames;
244
245 // SAFE ->
246 std::unique_lock aLock(m_aMutex);
247
248 impl_loadOnDemand(aLock);
249
250 try
251 {
252 FilterCache* pCache = impl_getWorkingCache(aLock);
253 std::vector<OUString> lKeys = pCache->getItemNames(m_eType);
254 lNames = comphelper::containerToSequence(lKeys);
255 }
256 catch(const css::uno::Exception&)
257 {
258 // invalid cache!?
259 lNames.realloc(0);
260 }
261
262 // <- SAFE
263
264 return lNames;
265}
266
267
268sal_Bool SAL_CALL BaseContainer::hasByName(const OUString& sItem)
269{
270 bool bHasOne = false;
271
272 // SAFE ->
273 std::unique_lock aLock(m_aMutex);
274
275 impl_loadOnDemand(aLock);
276
277 try
278 {
279 FilterCache* pCache = impl_getWorkingCache(aLock);
280 bHasOne = pCache->hasItem(m_eType, sItem);
281 }
282 catch(const css::uno::Exception&)
283 {
284 // invalid cache!?
285 bHasOne = false;
286 }
287
288 // <- SAFE
289
290 return bHasOne;
291}
292
293
294css::uno::Type SAL_CALL BaseContainer::getElementType()
295{
296 // no lock necessary - because the type of our items
297 // is fix! no internal call or member needed ...
299}
300
301
303{
304 bool bHasSome = false;
305
306 // SAFE ->
307 std::unique_lock aLock(m_aMutex);
308
309 impl_loadOnDemand(aLock);
310
311 try
312 {
313 FilterCache* pCache = impl_getWorkingCache(aLock);
314 bHasSome = pCache->hasItems(m_eType);
315 }
316 catch(const css::uno::Exception&)
317 {
318 // invalid cache?!
319 bHasSome = false;
320 }
321
322 // <- SAFE
323
324 return bHasSome;
325}
326
327
328css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const OUString& /* sQuery */ )
329{
330 OSL_FAIL("not pure virtual ... but not really implemented .-)");
331
332 return new ::comphelper::OEnumerationByName(this, {});
333}
334
335
336css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
337{
338 std::vector<OUString> lKeys;
339
340 // SAFE ->
341 std::unique_lock aLock(m_aMutex);
342
343 impl_loadOnDemand(aLock);
344
345 try
346 {
347 // search the key names of all items, where its properties match
348 // the given ones in its minimum
349 FilterCache* pCache = impl_getWorkingCache(aLock);
350 lKeys = pCache->getMatchingItemsByProps(m_eType, o3tl::span<const css::beans::NamedValue>( lProperties.getConstArray(), lProperties.getLength() ));
351 }
352 catch(const css::uno::Exception&)
353 {
354 // invalid cache, internal failure, wrong conversion ...!?
355 // doesn't matter
356 lKeys.clear();
357 }
358
359 // <- SAFE
360
361 // create a specialized enumeration helper, which
362 // provides the collected information outside.
363 // It hold a reference to us ... and call our container interface directly.
364 // be aware of some direct callbacks if it will be created :-)
365
366 /* Note: It's not allowed to return NULL. Because an empty enumeration
367 transport the same information but make no trouble outside.
368 Further its easier to work directly with the return value
369 instead of checking of NULL returns! */
370
371 return new ::comphelper::OEnumerationByName(this, std::move(lKeys));
372}
373
374
375void SAL_CALL BaseContainer::flush()
376{
377 // SAFE ->
378 std::unique_lock aLock(m_aMutex);
379
380 if (!m_pFlushCache)
381 throw css::lang::WrappedTargetRuntimeException(
382 "Can not guarantee cache consistency. Special flush container does not exists!",
383 getXWeak(),
384 css::uno::Any());
385
386 try
387 {
388 m_pFlushCache->flush();
389 // Take over all changes into the global cache and
390 // forget the clone.
391 /* TODO
392 -think about me
393 If the global cache gets this information via listener,
394 we should remove this method!
395 */
397 }
398 catch(const css::uno::Exception& ex)
399 {
400 // Don't remove the clone. May be the outside
401 // user wish to repair it now and calls flush()
402 // later again ...
403
404 throw css::lang::WrappedTargetRuntimeException( "Flush rejected by internal container.",
405 getXWeak(),
406 css::uno::Any(ex));
407 }
408
409 m_pFlushCache.reset();
410
411 css::lang::EventObject aSource (static_cast< css::util::XFlushable* >(this));
412 m_lListener.notifyEach( aLock, &css::util::XFlushListener::flushed, aSource);
413
414 // <- SAFE
415}
416
417
418void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
419{
420 std::unique_lock g(m_aMutex);
421 m_lListener.addInterface(g, xListener);
422}
423
424
425void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
426{
427 std::unique_lock g(m_aMutex);
428 m_lListener.removeInterface(g, xListener);
429}
430
431} // namespace filter::config
432
433/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr OUStringLiteral sImplementationName
constexpr OUStringLiteral sServiceName
sal_Int32 addInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
void notifyEach(std::unique_lock< std::mutex > &rGuard, void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event) const
sal_Int32 removeInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
OUString m_sImplementationName
the implementation name of our derived class, which we provide at the interface XServiceInfo of our c...
void init(const OUString &sImplementationName, const css::uno::Sequence< OUString > &lServiceNames, FilterCache::EItemType eType)
initialize this generic instance with some specialized values from our derived object.
virtual ~BaseContainer() override
standard dtor.
virtual sal_Bool SAL_CALL hasByName(const OUString &sItem) override
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue > &lProperties) override
virtual void SAL_CALL replaceByName(const OUString &sItem, const css::uno::Any &aValue) override
virtual void SAL_CALL removeByName(const OUString &sItem) override
virtual void SAL_CALL flush() override
FilterCache * impl_getWorkingCache(std::unique_lock< std::mutex > &rGuard) const
returns a pointer to the current used cache member.
virtual css::uno::Type SAL_CALL getElementType() override
FilterCache::EItemType m_eType
specify, which sub container of the used filter cache must be wrapped by this container interface.
std::unique_ptr< FilterCache > m_pFlushCache
local filter cache, which is used to collect changes on the filter configuration first and flush it l...
virtual sal_Bool SAL_CALL hasElements() override
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery(const OUString &sQuery) override
void impl_initFlushMode(std::unique_lock< std::mutex > &rGuard)
it creates the global instance m_pFilterCache, which is a copy of the global instance m_rCache,...
void impl_loadOnDemand(std::unique_lock< std::mutex > &rGuard)
check if the underlying configuration data was already loaded and do it if necessary automatically.
virtual OUString SAL_CALL getImplementationName() override
css::uno::Sequence< OUString > m_lServiceNames
the list of supported uno service names of our derived class, which we provide at the interface XServ...
virtual css::uno::Any SAL_CALL getByName(const OUString &sItem) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL removeFlushListener(const css::uno::Reference< css::util::XFlushListener > &xListener) override
virtual void SAL_CALL insertByName(const OUString &sItem, const css::uno::Any &aValue) override
virtual void SAL_CALL addFlushListener(const css::uno::Reference< css::util::XFlushListener > &xListener) override
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
comphelper::OInterfaceContainerHelper4< css::util::XFlushListener > m_lListener
holds all listener, which are registered at this instance.
virtual sal_Bool SAL_CALL supportsService(const OUString &sServiceName) override
represent an item of a FilterCache instance.
Definition: cacheitem.hxx:40
implements a cache, which contains all elements of our filter and type detection configuration.
Definition: filtercache.hxx:61
std::unique_ptr< FilterCache > clone() const
creates a copy of this container.
bool hasItems(EItemType eType) const
indicates if the requested sub container contains some items.
std::vector< OUString > getMatchingItemsByProps(EItemType eType, o3tl::span< const css::beans::NamedValue > lIProps, o3tl::span< const css::beans::NamedValue > lEProps={}) const
return a list of key names for items, which match the specified criteria.
EFillState
indicates, which items already exists inside this cache and which not.
Definition: filtercache.hxx:96
std::vector< OUString > getItemNames(EItemType eType) const
return a list of all key names, which represent an item inside the specified sub container.
bool hasItem(EItemType eType, const OUString &sItem)
check if the required item exist inside this container.
void load(EFillState eRequired)
force special fill state of this cache.
EItemType
identify the type of a container item.
Definition: filtercache.hxx:74
css::uno::Any getItemWithStateProps(EItemType eType, const OUString &sItem)
add some implicit properties to the given cache item reference.
void removeItem(EItemType eType, const OUString &sItem)
TODO document me ...
void takeOver(const FilterCache &rClone)
copy the cache content or rClone back to this instance.
void setItem(EItemType eType, const OUString &sItem, const CacheItem &aValue)
TODO document me ...
const EnumerationType m_eType
DocumentType eType
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
FilterCache & GetTheFilterCache()
unsigned char sal_Bool