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