merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / api2 / listenercontainer.hxx
blobcff7a1ff928d58658bf00d816ba336a9018d52ce
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: listenercontainer.hxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #ifndef CONFIGMGR_API_LISTENERCONTAINER_HXX_
32 #define CONFIGMGR_API_LISTENERCONTAINER_HXX_
34 #include <com/sun/star/lang/XEventListener.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <cppuhelper/interfacecontainer.hxx>
37 #include "datalock.hxx"
38 #include "utility.hxx"
40 #include <osl/diagnose.h>
42 namespace configmgr
44 namespace configapi
46 /////////////////////////////////////////////////////////////////////////////////////////////
48 namespace css = ::com::sun::star;
49 namespace uno = css::uno;
50 namespace lang = css::lang;
51 //-----------------------------------------------------------------------------
52 template <class Listener>
53 class ListenerContainerIterator
55 public:
56 /**
57 * Create an iterator over the elements of the container. The iterator
58 * copies the elements of the conatainer. A change to the container does not
59 * affect the iterator.<BR>
60 * Remark: The copy is on demand. The iterator copy the elements only if the container
61 * change the contens. It is not allowed to destroy the container if a iterator exist.
63 * @param rCont the container of the elements.
65 ListenerContainerIterator( cppu::OInterfaceContainerHelper& rCont )
66 : m_aIter(rCont)
67 , m_xNext()
68 { advance(); }
70 /**
71 * Release the connection to the container.
73 ~ListenerContainerIterator() {}
75 /** Return true, if there are more elements in the iterator. */
76 sal_Bool hasMoreElements() const { return m_xNext.is() != 0; }
78 /** Return the next element of the iterator. Call this method if
79 * hasMoreElements return false, is an error.
81 uno::Reference<Listener> next();
83 private:
84 void advance();
86 cppu::OInterfaceIteratorHelper m_aIter;
87 uno::Reference<Listener> m_xNext;
89 //-----------------------------------------------------------------------------
90 class DisposeNotifier
92 lang::EventObject aEvent;
93 std::vector< uno::Reference< lang::XEventListener > > aListeners;
94 public:
95 explicit
96 DisposeNotifier(uno::Reference<uno::XInterface> const& aInterface) : aEvent(aInterface) {}
98 void appendAndClearContainer(cppu::OInterfaceContainerHelper* pContainer);
99 void notify();
101 //-----------------------------------------------------------------------------
102 struct BasicContainerInfo
104 uno::XInterface* pInterface;
105 cppu::OMultiTypeInterfaceContainerHelper* pContainer;
106 BasicContainerInfo() : pInterface(0), pContainer(0) {}
109 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
110 class SpecialListenerContainer
112 public:
114 * Create a container of interface containers.
116 SpecialListenerContainer(std::vector<BasicContainerInfo>::size_type nCount, KeyToIndex_ aMapper)
117 : m_aSpecialHelper(UnoApiLock::getLock())
118 , m_aContainers(nCount)
119 , m_aMapper(aMapper)
120 , m_bDisposeLock(false)
123 ~SpecialListenerContainer()
125 OSL_ENSURE(isDisposed(), "ERROR: Object was not disposed properly");
127 public:
129 * check whether this is disposed or still alive
130 * @param pObject
131 * an interface on the object on which's behalf the operation was started
132 * @return <FALSE/>
133 * if the object is being disposed
134 * @throw com::sun::star::lang::DisposedException
135 * if the object was disposed completely
137 bool checkAlive(uno::XInterface* pObject = 0) volatile const throw(lang::DisposedException);
139 /// return whether the object is completely alive
140 bool isAlive() volatile const throw();
141 /// return whether the object is currently being disposed
142 bool isDisposing()volatile const throw();
143 /// return whether the object is completely disposed
144 bool isDisposed()volatile const throw();
146 /// return whether the object is present in this container
147 bool isAvailable(std::vector<BasicContainerInfo>::size_type nIndex) const throw()
149 return nIndex < m_aContainers.size() && m_aContainers[nIndex].pInterface;
152 std::vector<BasicContainerInfo>::size_type getSize() const
154 return m_aContainers.size();
157 /// return the interface associated with an index
158 void setObjectAt(std::vector<BasicContainerInfo>::size_type nIndex, uno::XInterface* pInterface)
160 OSL_ENSURE( !isDisposed(), "object is disposed" );
162 if (isAlive())
164 OSL_ENSURE( nIndex < m_aContainers.size(), " Invalid Index into Notifier");
165 OSL_ENSURE( pInterface, "Invalid NULL Interface passed into Notifier");
167 if ( nIndex < m_aContainers.size() && pInterface != NULL)
169 OSL_ENSURE( m_aContainers[nIndex].pInterface == NULL, "Interface already set");
170 if (m_aContainers[nIndex].pInterface == NULL)
171 m_aContainers[nIndex].pInterface = pInterface;
177 /// return the interface associated with an index
178 uno::Reference<uno::XInterface> getObjectAt(std::vector<BasicContainerInfo>::size_type nIndex) const
180 uno::Reference<uno::XInterface> xRet( nIndex < m_aContainers.size() ? m_aContainers[nIndex].pInterface : 0 );
181 return xRet;
184 /// return the interface associated with an index
185 uno::Reference<uno::XInterface> getObjectForKey(Key_ const& aKey ) const
187 std::vector<BasicContainerInfo>::size_type nIndex = m_aMapper.findIndexForKey(aKey);
188 uno::Reference<uno::XInterface> xRet( nIndex < m_aContainers.size() ? m_aContainers[nIndex].pInterface : 0 );
189 return xRet;
193 * Call disposing on all object in all the container for anIndex
194 * and in the containers for the associated indices
195 * support XEventListener. Then clear the container.
197 bool disposeOne( std::vector<BasicContainerInfo>::size_type anIndex ) throw();
200 * Start disposing this object
201 * @return <TRUE/>
202 * if disposing has been started
203 * @return <FALSE/>
204 * if disposing had already been started before
206 bool beginDisposing() throw();
208 * Continue disposing this object
209 * <p> Call disposing on all object in all the containers that
210 * support XEventListener. Then clear the container.
211 * </p>
212 * @return <TRUE/>
213 * if disposing has been started
214 * @return <FALSE/>
215 * if disposing had already been started before
217 void notifyDisposing() throw();
219 /// mark the end of the dispose processing
220 void endDisposing() throw();
222 public:
224 * Return the specuial container created under this key.
225 * @return the container created under this key. If the container
226 * was not created, null was returned.
228 cppu::OInterfaceContainerHelper * getSpecialContainer( const Key_ & aKey) const
229 { return m_aSpecialHelper.aLC.getContainer(aKey); }
232 * Return the containerhelper created under this index.
233 * @return the container helper created under this key. If the container helper
234 * was not created, null was returned.
236 cppu::OMultiTypeInterfaceContainerHelper * getContainerHelper( std::vector<BasicContainerInfo>::size_type nIndex) const
238 return ((nIndex < m_aContainers.size()) ? m_aContainers[nIndex].pContainer : 0 );
241 * Return the container for the given type created under this index.
242 * @return the container created under this key. If the container
243 * was not created, null was returned.
245 cppu::OInterfaceContainerHelper * getContainer( std::vector<BasicContainerInfo>::size_type nIndex, const uno::Type & aType) const
247 cppu::OMultiTypeInterfaceContainerHelper* pContainer = (nIndex < m_aContainers.size()) ? m_aContainers[nIndex].pContainer : 0 ;
249 return pContainer ? pContainer->getContainer(aType) : 0;
253 * Insert an element in the container specified with the index and type. The position is not specified.
254 * The interface at the given index must be set already.
255 * @param aKey the id of the container.
256 * @param xListener the added interface. It is allowed to insert null or
257 * the same pointer more than once.
258 * @return the new count of elements in the container (or 0 if the object is ready being disposed).
260 sal_Int32 addListener( std::vector<BasicContainerInfo>::size_type nIndex, const uno::Type& aType, uno::Reference< lang::XEventListener > const& xListener) throw();
263 * Remove an element from the container specified with the index and type.
264 * It uses the equal definition of uno objects to remove the interfaces.
265 * @param aKey the id of the container.
266 * @param xListener the removed interface.
267 * @return the new count of elements in the container (or 0 if the object is ready being disposed).
269 sal_Int32 removeListener( std::vector<BasicContainerInfo>::size_type nIndex, const uno::Type& aType, uno::Reference< lang::XEventListener > const& xListener) throw();
273 * Insert an element in the special container specified with the key. The position is not specified.
274 * The interface at the given index must be set already.
275 * @param aKey the id of the container.
276 * @param xListener the added interface. It is allowed to insert null or
277 * the same pointer more than once.
278 * @return the new count of elements in the container (or 0 if the object is ready being disposed).
280 sal_Int32 addSpecialListener( const Key_& aKey, uno::Reference< lang::XEventListener > const& xListener) throw();
283 * Remove an element from the container specified with the key.
284 * It uses the equal definition of uno objects to remove the interfaces.
285 * @param aKey the id of the container.
286 * @param xListener the removed interface.
287 * @return the new count of elements in the container (or 0 if the object is ready being disposed).
289 sal_Int32 removeSpecialListener( const Key_& aKey, uno::Reference< lang::XEventListener > const& xListener) throw();
291 private:
292 void implFillDisposer(DisposeNotifier& aNotifier, std::vector<BasicContainerInfo>::size_type nIndex);
294 cppu::OBroadcastHelperVar< cppu::OMultiTypeInterfaceContainerHelperVar< Key_,KeyHash_,KeyEq_ >, Key_ > m_aSpecialHelper;
295 std::vector<BasicContainerInfo> m_aContainers;
296 KeyToIndex_ m_aMapper;
297 bool m_bDisposeLock;
299 //-----------------------------------------------------------------------------
301 /////////////////////////////////////////////////////////////////////////////////////////////
302 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
303 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::checkAlive(uno::XInterface* pObject) volatile const throw(lang::DisposedException)
305 bool bAlive = !m_aSpecialHelper.bInDispose;
306 if (m_aSpecialHelper.bDisposed)
308 throw lang::DisposedException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("The object has already been disposed")),pObject);
310 return bAlive;
312 //-----------------------------------------------------------------------------
313 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
314 inline
315 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::isAlive() volatile const throw()
317 return !m_aSpecialHelper.bInDispose && !m_aSpecialHelper.bDisposed;
319 //-----------------------------------------------------------------------------
320 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
321 inline
322 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::isDisposing() volatile const throw()
324 return !!m_aSpecialHelper.bInDispose;
326 //-----------------------------------------------------------------------------
327 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
328 inline
329 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::isDisposed() volatile const throw()
331 return !!m_aSpecialHelper.bDisposed;
333 //-----------------------------------------------------------------------------
334 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
335 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::disposeOne(std::vector<BasicContainerInfo>::size_type nIndex) throw()
337 // OSL_ENSURE(!isDisposed(),"Object is already disposed in toto");
338 if (isAlive())
340 if (nIndex < m_aContainers.size())
342 if (uno::XInterface* pObject = m_aContainers[nIndex].pInterface)
344 DisposeNotifier aNotifier(pObject);
346 implFillDisposer(aNotifier, nIndex);
347 m_aContainers[nIndex].pInterface = 0;
348 delete m_aContainers[nIndex].pContainer;
350 aNotifier.notify();
353 return true;
355 else
356 return false;
358 //-----------------------------------------------------------------------------
359 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
360 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::beginDisposing() throw()
362 if (isAlive())
364 m_aSpecialHelper.bInDispose = sal_True;
365 m_bDisposeLock = true;
367 return true;
369 return false;
371 //-----------------------------------------------------------------------------
372 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
373 void SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::notifyDisposing() throw()
375 OSL_ENSURE(isDisposing(),"Disposing isn't in progress on this object");
376 OSL_ENSURE(m_bDisposeLock,"Duplicate call for dispose notification or disposing is not taking place");
378 if (m_bDisposeLock)
380 OSL_ASSERT(m_aSpecialHelper.bInDispose);
382 lang::EventObject aBaseEvt;
383 std::vector<DisposeNotifier> aNotifiers;
385 if (std::vector<BasicContainerInfo>::size_type size = m_aContainers.size())
387 aNotifiers.reserve(m_aContainers.size());
389 aBaseEvt.Source = m_aContainers[0].pInterface;
390 for(std::vector<BasicContainerInfo>::size_type ix = 0; ix < size; ++ix)
392 if (m_aContainers[ix].pInterface)
394 aNotifiers.push_back(DisposeNotifier(m_aContainers[ix].pInterface));
395 implFillDisposer(aNotifiers.back(), ix);
396 m_aContainers[ix].pInterface = 0;
397 delete m_aContainers[ix].pContainer;
402 m_bDisposeLock = false;
404 for(std::vector<BasicContainerInfo>::size_type jx = 0, count = aNotifiers.size(); jx < count; ++jx)
406 aNotifiers[jx].notify();
408 // in case we missed something
409 m_aSpecialHelper.aLC.disposeAndClear( aBaseEvt );
412 //-----------------------------------------------------------------------------
413 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
414 void SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::endDisposing() throw()
416 OSL_ENSURE(isDisposing(),"Disposing isn't in progress on this object");
418 if (!isAlive())
420 OSL_ENSURE(!m_bDisposeLock,"Did you forget to notify ?");
422 m_aSpecialHelper.bDisposed = sal_True;
423 m_aSpecialHelper.bInDispose = sal_False;
425 if (m_bDisposeLock)
427 m_bDisposeLock = false;
431 //-----------------------------------------------------------------------------
432 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
433 sal_Int32 SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::addListener( std::vector<BasicContainerInfo>::size_type nIndex, const uno::Type& aType, const uno::Reference< lang::XEventListener > & xListener ) throw()
435 if ( nIndex < m_aContainers.size() && m_aContainers[nIndex].pInterface )
437 if ( isAlive() )
439 if (m_aContainers[nIndex].pContainer == 0)
440 m_aContainers[nIndex].pContainer = new cppu::OMultiTypeInterfaceContainerHelper(UnoApiLock::getLock());
442 return m_aContainers[nIndex].pContainer->addInterface(aType,xListener);
445 else if (xListener.is())
447 lang::EventObject aEvent(m_aContainers[nIndex].pInterface);
448 try { xListener->disposing(aEvent); } catch (uno::Exception & ) {}
452 else
453 OSL_ENSURE(false, "Invalid index or interface not set");
455 return 0;
457 //-----------------------------------------------------------------------------
458 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
459 sal_Int32 SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::addSpecialListener( const Key_& aKey, const uno::Reference< lang::XEventListener > & xListener ) throw()
461 std::vector<BasicContainerInfo>::size_type nIndex = m_aMapper.findIndexForKey(aKey);
462 if ( nIndex < m_aContainers.size() && m_aContainers[nIndex].pInterface )
464 if ( isAlive() )
466 return m_aSpecialHelper.aLC.addInterface(aKey,xListener);
469 else if (xListener.is())
471 lang::EventObject aEvent(m_aContainers[nIndex].pInterface);
472 try { xListener->disposing(aEvent); } catch (uno::Exception & ) {}
475 else
476 OSL_ENSURE(false, "Invalid index or interface not set");
478 return 0;
480 //-----------------------------------------------------------------------------
482 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
483 sal_Int32 SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::removeListener( std::vector<BasicContainerInfo>::size_type nIndex, const uno::Type& aType, const uno::Reference< lang::XEventListener > & xListener ) throw()
485 OSL_ENSURE( !isDisposed(), "object is disposed" );
487 if ( isAlive() )
489 if ( nIndex < m_aContainers.size() && m_aContainers[nIndex].pContainer )
491 return m_aContainers[nIndex].pContainer->removeInterface(aType,xListener);
494 return 0;
496 //-----------------------------------------------------------------------------
498 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
499 sal_Int32 SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::removeSpecialListener( const Key_& aKey, const uno::Reference< lang::XEventListener > & xListener ) throw()
501 OSL_ENSURE( !isDisposed(), "object is disposed" );
503 if ( isAlive() )
504 return m_aSpecialHelper.aLC.removeInterface(aKey, xListener );
506 else
507 return 0;
509 //-----------------------------------------------------------------------------
510 // relation function. Uses KeyToIndex
511 /* template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
512 SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::Index
513 SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::findIndexForKey(Key const& aKey)
515 m_aMapper.findIndexForKey(aKey);
517 //-----------------------------------------------------------------------------
518 // relation function. Uses KeyToIndex
519 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
520 bool SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::findKeysForIndex(std::vector<BasicContainerInfo>::size_type nIndex, std::vector<Key_> & aKeys)
522 aKeys.clear();
523 m_aMapper.findKeysForIndex(nIndex,aKeys);
524 return !aKeys.empty();
526 *///-----------------------------------------------------------------------------
527 // relation function. Uses KeyToIndex
528 template <class Key_, class KeyHash_, class KeyEq_, class KeyToIndex_>
529 void SpecialListenerContainer<Key_,KeyHash_,KeyEq_, KeyToIndex_>::implFillDisposer(DisposeNotifier& aNotifier, std::vector<BasicContainerInfo>::size_type nIndex)
531 if (cppu::OMultiTypeInterfaceContainerHelper* pMultiContainer = m_aContainers[nIndex].pContainer)
533 uno::Sequence< uno::Type > aTypes(pMultiContainer->getContainedTypes());
534 for (sal_Int32 ix = 0; ix < aTypes.getLength(); ++ix)
536 cppu::OInterfaceContainerHelper* pContainer = pMultiContainer->getContainer(aTypes[ix]);
537 OSL_ENSURE(pContainer,"No container, but the type ?");
538 if (pContainer)
539 aNotifier.appendAndClearContainer(pContainer);
542 std::vector<Key_> aKeys;
543 if (m_aMapper.findKeysForIndex(nIndex,aKeys))
545 for(typename std::vector<Key_>::iterator it = aKeys.begin(); it != aKeys.end(); ++it)
547 if (cppu::OInterfaceContainerHelper* pContainer = m_aSpecialHelper.aLC.getContainer(*it))
549 aNotifier.appendAndClearContainer(pContainer);
554 //-----------------------------------------------------------------------------
556 /////////////////////////////////////////////////////////////////////////////////////////////
558 template <class Listener>
559 inline
560 void ListenerContainerIterator<Listener>::advance()
562 while (!m_xNext.is() && m_aIter.hasMoreElements())
564 m_xNext = m_xNext.query( m_aIter.next() );
567 //-----------------------------------------------------------------------------
569 template <class Listener>
570 uno::Reference<Listener> ListenerContainerIterator<Listener>::next()
572 uno::Reference<Listener> xRet(m_xNext);
573 m_xNext.clear();
574 advance();
575 return xRet;
577 //-----------------------------------------------------------------------------
579 /////////////////////////////////////////////////////////////////////////////////////////////
582 #endif // CONFIGMGR_API_LISTENERCONTAINER_HXX_