1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_
29 #define _DBA_CORE_DEFINITIONCONTAINER_HXX_
30 
31 #ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_
32 #include <cppuhelper/interfacecontainer.hxx>
33 #endif
34 #ifndef _CPPUHELPER_IMPLBASE7_HXX_
35 #include <cppuhelper/implbase7.hxx>
36 #endif
37 #ifndef _COMPHELPER_STLTYPES_HXX_
38 #include <comphelper/stl_types.hxx>
39 #endif
40 #ifndef _OSL_MUTEX_HXX_
41 #include <osl/mutex.hxx>
42 #endif
43 #ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
44 #include <com/sun/star/container/XChild.hpp>
45 #endif
46 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
47 #include <com/sun/star/container/XNameContainer.hpp>
48 #endif
49 #ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_
50 #include <com/sun/star/container/XContainer.hpp>
51 #endif
52 #ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
53 #include <com/sun/star/container/XEnumerationAccess.hpp>
54 #endif
55 #ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
56 #include <com/sun/star/container/XIndexAccess.hpp>
57 #endif
58 #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
59 #include <com/sun/star/lang/XServiceInfo.hpp>
60 #endif
61 #ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
62 #include <com/sun/star/lang/DisposedException.hpp>
63 #endif
64 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_
65 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
66 #endif
67 #ifndef _COM_SUN_STAR_BEANS_XVETOABLECHANGELISTENER_HPP_
68 #include <com/sun/star/beans/XVetoableChangeListener.hpp>
69 #endif
70 #ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVEBROADCASTER_HPP_
71 #include <com/sun/star/container/XContainerApproveBroadcaster.hpp>
72 #endif
73 #ifndef DBA_CONTENTHELPER_HXX
74 #include "ContentHelper.hxx"
75 #endif
76 #ifndef DBACCESS_CONTAINERAPPROVE_HXX
77 #include "containerapprove.hxx"
78 #endif
79 #ifndef _COMPHELPER_UNO3_HXX_
80 #include <comphelper/uno3.hxx>
81 #endif
82 #ifndef _RTL_REF_HXX_
83 #include <rtl/ref.hxx>
84 #endif
85 #ifndef _DBASHARED_APITOOLS_HXX_
86 #include "apitools.hxx"
87 #endif
88 //........................................................................
89 namespace dbaccess
90 {
91 //........................................................................
92 
93 class ODefinitionContainer_Impl : public OContentHelper_Impl
94 {
95 public:
96     typedef ::std::map< ::rtl::OUString, TContentPtr >  NamedDefinitions;
97     typedef NamedDefinitions::iterator                  iterator;
98     typedef NamedDefinitions::const_iterator            const_iterator;
99 
100 private:
101 	NamedDefinitions    m_aDefinitions;
102 
103 public:
104     inline size_t size() const { return m_aDefinitions.size(); }
105 
106     inline const_iterator begin() const   { return m_aDefinitions.begin(); }
107     inline const_iterator end() const     { return m_aDefinitions.end(); }
108 
109     inline const_iterator find( const ::rtl::OUString& _rName ) const { return m_aDefinitions.find( _rName ); }
110            const_iterator find( TContentPtr _pDefinition ) const;
111 
112     inline void erase( const ::rtl::OUString& _rName ) { m_aDefinitions.erase( _rName ); }
113     void erase( TContentPtr _pDefinition );
114 
115     inline void insert( const ::rtl::OUString& _rName, TContentPtr _pDefinition )
116     {
117         m_aDefinitions.insert( NamedDefinitions::value_type( _rName, _pDefinition ) );
118     }
119 
120 private:
121     iterator find( TContentPtr _pDefinition );
122         // (for the moment, this is private. Make it public if needed. If really needed.)
123 };
124 
125 //==========================================================================
126 //= ODefinitionContainer -	base class of collections of database definition
127 //=							documents
128 //==========================================================================
129 typedef ::cppu::ImplHelper7 <   ::com::sun::star::container::XIndexAccess
130                             ,   ::com::sun::star::container::XNameContainer
131                             ,   ::com::sun::star::container::XEnumerationAccess
132                             ,   ::com::sun::star::container::XContainer
133                             ,   ::com::sun::star::container::XContainerApproveBroadcaster
134                             ,   ::com::sun::star::beans::XPropertyChangeListener
135                             ,   ::com::sun::star::beans::XVetoableChangeListener
136                             >   ODefinitionContainer_Base;
137 
138 class ODefinitionContainer
139 			:public OContentHelper
140 			,public ODefinitionContainer_Base
141 {
142 protected:
143 	DECLARE_STL_USTRINGACCESS_MAP(::com::sun::star::uno::WeakReference< ::com::sun::star::ucb::XContent >, Documents);
144 	DECLARE_STL_VECTOR(Documents::iterator, DocumentsIndexAccess);
145 
146 	enum ContainerOperation
147 	{
148 		E_REPLACED,
149 		E_REMOVED,
150 		E_INSERTED
151 	};
152 
153     enum ListenerType
154     {
155         ApproveListeners,
156         ContainerListemers
157     };
158 
159 private:
160     PContainerApprove   m_pElementApproval;
161 
162 protected:
163 	// we can't just hold a vector of XContentRefs, as after initialization they're all empty
164 	// cause we load them only on access
165 	DocumentsIndexAccess	m_aDocuments;				// for a efficient index access
166 	Documents				m_aDocumentMap;				// for a efficient name access
167 
168     ::cppu::OInterfaceContainerHelper
169                             m_aApproveListeners;
170 	::cppu::OInterfaceContainerHelper
171 							m_aContainerListeners;
172 
173     sal_Bool				m_bInPropertyChange;
174     bool                    m_bCheckSlash;
175 
176 protected:
177     /** Additionally to our own approvals which new elements must pass, derived classes
178         can specifiy an additional approval instance here.
179 
180         Every time a new element is inserted into the container (or an element is replaced
181         with a new one), this new element must pass our own internal approval, plus the approval
182         given here.
183     */
184     void                setElementApproval( PContainerApprove _pElementApproval ) { m_pElementApproval = _pElementApproval; }
185     PContainerApprove   getElementApproval() const { return m_pElementApproval; }
186 
187 protected:
188     virtual ~ODefinitionContainer();
189 
190     inline const ODefinitionContainer_Impl& getDefinitions() const
191     {
192         return dynamic_cast< const ODefinitionContainer_Impl& >( *m_pImpl.get() );
193     }
194 
195     inline       ODefinitionContainer_Impl&  getDefinitions()
196     {
197         return dynamic_cast<       ODefinitionContainer_Impl& >( *m_pImpl.get() );
198     }
199 public:
200 	/** constructs the container.
201 	*/
202 	ODefinitionContainer(
203 		  const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB
204 		, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&	_xParentContainer
205 		, const TContentPtr& _pImpl
206         , bool _bCheckSlash = true
207 		);
208 
209 // ::com::sun::star::uno::XInterface
210 	DECLARE_XINTERFACE( )
211 // com::sun::star::lang::XTypeProvider
212 	DECLARE_TYPEPROVIDER( );
213 
214 // ::com::sun::star::lang::XServiceInfo
215 	virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
216 	virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);
217 
218 // ::com::sun::star::container::XElementAccess
219 	virtual ::com::sun::star::uno::Type SAL_CALL getElementType(  ) throw(::com::sun::star::uno::RuntimeException);
220 	virtual sal_Bool SAL_CALL hasElements(  ) throw(::com::sun::star::uno::RuntimeException);
221 
222 // ::com::sun::star::container::XEnumerationAccess
223 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration(  ) throw(::com::sun::star::uno::RuntimeException);
224 
225 // ::com::sun::star::container::XIndexAccess
226 	virtual sal_Int32 SAL_CALL getCount(  ) throw(::com::sun::star::uno::RuntimeException);
227 	virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 _nIndex ) throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
228 
229 // ::com::sun::star::container::XNameContainer
230     virtual void SAL_CALL insertByName( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Any& aElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
231     virtual void SAL_CALL removeByName( const ::rtl::OUString& _rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
232 
233 // ::com::sun::star::container::XNameReplace
234     virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Any& aElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
235 
236 // ::com::sun::star::container::XNameAccess
237 	virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
238 	virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw(::com::sun::star::uno::RuntimeException);
239 	virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException);
240 
241 // ::com::sun::star::container::XContainer
242     virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException);
243     virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException);
244 
245     // XContainerApproveBroadcaster
246     virtual void SAL_CALL addContainerApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerApproveListener >& Listener ) throw (::com::sun::star::uno::RuntimeException);
247     virtual void SAL_CALL removeContainerApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerApproveListener >& Listener ) throw (::com::sun::star::uno::RuntimeException);
248 
249 // ::com::sun::star::lang::XEventListener
250 	virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException);
251 
252 	// XPropertyChangeListener
253 	virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException);
254 	// XVetoableChangeListener
255 	virtual void SAL_CALL vetoableChange( const ::com::sun::star::beans::PropertyChangeEvent& aEvent ) throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException);
256 
257 protected:
258 	// helper
259 	virtual void SAL_CALL disposing();
260 
261 	/** create a object from it's persistent data within the configuration. To be overwritten by derived classes.
262 		@param		_rName			the name the object has within the container
263 		@return						the newly created object or an empty reference if somthing went wrong
264 	*/
265 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > createObject(
266 		const ::rtl::OUString& _rName) = 0;
267 
268 	/** get the object specified by the given name. If desired, the object will be read if not already done so.<BR>
269 		@param		_rName				the object name
270 		@param		_bReadIfNeccessary	if sal_True, the object will be created if necessary
271 		@return							the property set interface of the object. Usually the return value is not NULL, but
272 										if so, then the object could not be read from the configuration
273 		@throws							NoSuchElementException if there is no object with the given name.
274 		@see	createObject
275 	*/
276 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >
277 				implGetByName(const ::rtl::OUString& _rName, sal_Bool _bCreateIfNecessary) throw (::com::sun::star::container::NoSuchElementException);
278 
279 	/** quickly checks if there already is an element with a given name. No access to the configuration occures, i.e.
280 		if there is such an object which is not already loaded, it won't be loaded now.
281 		@param		_rName		the object name to check
282 		@return					sal_True if there already exists such an object
283 	*/
284 	virtual	sal_Bool checkExistence(const ::rtl::OUString& _rName);
285 
286 	/** append a new object to the container. No plausibility checks are done, e.g. if the object is non-NULL or
287 		if the name is already used by another object or anything like this. This method is for derived classes
288 		which may support different methods to create and/or append objects, and don't want to deal with the
289 		internal structures of this class.<BR>
290 		The old component will not be disposed, this is the callers responsibility, too.
291 		@param		_rName			the name of the new object
292 		@param		_rxNewObject	the new object (not surprising, is it ?)
293 		@see		createConfigKey
294 		@see		implReplace
295 		@see		implRemove
296 	*/
297 	void	implAppend(
298 		const ::rtl::OUString& _rName,
299 		const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxNewObject
300 		);
301 
302 	/** remove all references to an object from the container. No plausibility checks are done, e.g. whether
303 		or not there exists an object with the given name. This is the responsibility of the caller.<BR>
304 		Additionally the node for the given object will be removed from the registry (including all sub nodes).<BR>
305 		The old component will not be disposed, this is the callers responsibility, too.
306 		@param			_rName		the objects name
307 		@see			implReplace
308 		@see			implAppend
309 	*/
310 	void implRemove(const ::rtl::OUString& _rName);
311 
312 	/** remove a object in the container. No plausibility checks are done, e.g. whether
313 		or not there exists an object with the given name or the object is non-NULL. This is the responsibility of the caller.<BR>
314 		Additionally all object-related informations within the registry will be deleted. The new object config node,
315 		where the caller may want to store the new objects information, is returned.<BR>
316 		The old component will not be disposed, this is the callers responsibility, too.
317 		@param			_rName				the objects name
318 		@param			_rxNewObject		the new object
319 		@param			_rNewObjectNode		the configuration node where the new object may be stored
320 		@see			implAppend
321 		@see			implRemove
322 	*/
323 	void implReplace(
324 		const ::rtl::OUString& _rName,
325 		const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxNewObject
326 		);
327 
328     /** notifies our container/approve listeners
329     */
330 	void notifyByName(
331             ::osl::ResettableMutexGuard& _rGuard,
332 			const ::rtl::OUString& _rName,
333 			const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _xNewElement,
334 			const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& xOldElement,
335             ContainerOperation _eOperation,
336             ListenerType _eType
337         );
338 
339 	inline SAL_CALL operator ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > () const
340     {
341         return const_cast< XContainer* >( static_cast< const XContainer* >( this ) );
342     }
343 
344 private:
345 	void	addObjectListener(const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _xNewObject);
346 	void	removeObjectListener(const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _xNewObject);
347 
348     /** approve that the object given may be inserted into the container. Should be overloaded by derived classes,
349 		the default implementation just checks the object to be non-void.
350 
351         @throws IllegalArgumentException
352             if the name or the object are invalid
353         @throws ElementExistException
354             if the object already exists in the container, or another object with the same name
355             already exists
356         @throws WrappedTargetException
357             if another error occures which prevents insertion of the object into the container
358 	*/
359 	void approveNewObject(
360             const ::rtl::OUString& _sName,
361             const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxObject
362         ) const;
363 
364     inline bool impl_haveAnyListeners_nothrow() const
365     {
366         return ( m_aContainerListeners.getLength() > 0 ) || ( m_aApproveListeners.getLength() > 0 );
367     }
368 };
369 
370 //........................................................................
371 }	// namespace dbaccess
372 //........................................................................
373 
374 #endif // _DBA_CORE_DEFINITIONCONTAINER_HXX_
375 
376