update dev300-m58
[ooovba.git] / dbaccess / source / core / api / querycontainer.cxx
blob3a7e6a83f3272c15fa7602df1a9a70b670ecf104
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: querycontainer.cxx,v $
10 * $Revision: 1.27 $
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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #ifndef _DBA_CORE_QUERYCONTAINER_HXX_
35 #include "querycontainer.hxx"
36 #endif
37 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
38 #include "dbastrings.hrc"
39 #endif
40 #ifndef _DBA_COREAPI_QUERY_HXX_
41 #include "query.hxx"
42 #endif
43 #ifndef DBACCESS_OBJECTNAMEAPPROVAL_HXX
44 #include "objectnameapproval.hxx"
45 #endif
46 #ifndef DBA_CONTAINERLISTENER_HXX
47 #include "ContainerListener.hxx"
48 #endif
49 #ifndef DBACCESS_VETO_HXX
50 #include "veto.hxx"
51 #endif
53 /** === begin UNO includes === **/
54 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #endif
57 #ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_
58 #include <com/sun/star/container/XContainer.hpp>
59 #endif
60 #ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
61 #include <com/sun/star/sdbc/XConnection.hpp>
62 #endif
63 #ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVEBROADCASTER_HPP_
64 #include <com/sun/star/container/XContainerApproveBroadcaster.hpp>
65 #endif
66 /** === end UNO includes === **/
68 #ifndef _DBHELPER_DBEXCEPTION_HXX_
69 #include <connectivity/dbexception.hxx>
70 #endif
72 #ifndef _TOOLS_DEBUG_HXX
73 #include <tools/debug.hxx>
74 #endif
75 #ifndef _COMPHELPER_ENUMHELPER_HXX_
76 #include <comphelper/enumhelper.hxx>
77 #endif
78 #ifndef _COMPHELPER_UNO3_HXX_
79 #include <comphelper/uno3.hxx>
80 #endif
81 #ifndef _COMPHELPER_PROPERTY_HXX_
82 #include <comphelper/property.hxx>
83 #endif
84 #ifndef _COMPHELPER_SEQUENCE_HXX_
85 #include <comphelper/sequence.hxx>
86 #endif
87 #ifndef _COMPHELPER_EXTRACT_HXX_
88 #include <comphelper/extract.hxx>
89 #endif
90 #ifndef _CPPUHELPER_EXC_HLP_HXX_
91 #include <cppuhelper/exc_hlp.hxx>
92 #endif
94 using namespace dbtools;
95 using namespace ::com::sun::star::uno;
96 using namespace ::com::sun::star::ucb;
97 using namespace ::com::sun::star::lang;
98 using namespace ::com::sun::star::beans;
99 using namespace ::com::sun::star::sdb;
100 using namespace ::com::sun::star::sdbc;
101 using namespace ::com::sun::star::sdbcx;
102 using namespace ::com::sun::star::container;
103 using namespace ::com::sun::star::util;
104 using namespace ::osl;
105 using namespace ::comphelper;
106 using namespace ::cppu;
108 //........................................................................
109 namespace dbaccess
111 //........................................................................
113 //==========================================================================
114 //= OQueryContainer
115 //==========================================================================
116 DBG_NAME(OQueryContainer)
117 //------------------------------------------------------------------------------
118 OQueryContainer::OQueryContainer(
119 const Reference< XNameContainer >& _rxCommandDefinitions
120 , const Reference< XConnection >& _rxConn
121 , const Reference< XMultiServiceFactory >& _rxORB,
122 ::dbtools::IWarningsContainer* _pWarnings)
123 :ODefinitionContainer(_rxORB,NULL,TContentPtr(new ODefinitionContainer_Impl))
124 ,m_pWarnings( _pWarnings )
125 ,m_xCommandDefinitions(_rxCommandDefinitions)
126 ,m_xConnection(_rxConn)
128 DBG_CTOR(OQueryContainer, NULL);
130 increment(m_refCount);
132 m_pCommandsListener = new OContainerListener( *this, m_aMutex );
133 m_pCommandsListener->acquire();
135 Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY_THROW );
136 xContainer->addContainerListener( m_pCommandsListener );
138 Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY_THROW );
139 xContainerApprove->addContainerApproveListener( m_pCommandsListener );
141 // fill my structures
142 ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
143 Sequence< ::rtl::OUString > sDefinitionNames = m_xCommandDefinitions->getElementNames();
144 const ::rtl::OUString* pDefinitionName = sDefinitionNames.getConstArray();
145 const ::rtl::OUString* pEnd = pDefinitionName + sDefinitionNames.getLength();
146 for ( ; pDefinitionName != pEnd; ++pDefinitionName )
148 rDefinitions.insert( *pDefinitionName, TContentPtr() );
149 m_aDocuments.push_back(m_aDocumentMap.insert(Documents::value_type(*pDefinitionName,Documents::mapped_type())).first);
152 decrement(m_refCount);
154 setElementApproval( PContainerApprove( new ObjectNameApproval( _rxConn, ObjectNameApproval::TypeQuery ) ) );
157 //------------------------------------------------------------------------------
158 OQueryContainer::~OQueryContainer()
160 DBG_DTOR(OQueryContainer, NULL);
161 // dispose();
162 // maybe we're already disposed, but this should be uncritical
164 // -----------------------------------------------------------------------------
165 IMPLEMENT_FORWARD_XINTERFACE2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base)
166 //------------------------------------------------------------------------------
167 void OQueryContainer::disposing()
169 ODefinitionContainer::disposing();
170 MutexGuard aGuard(m_aMutex);
171 if ( !m_xCommandDefinitions.is() )
172 // already disposed
173 return;
175 if ( m_pCommandsListener )
177 Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY );
178 xContainer->removeContainerListener( m_pCommandsListener );
179 Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY );
180 xContainerApprove->removeContainerApproveListener( m_pCommandsListener );
182 m_pCommandsListener->dispose();
183 m_pCommandsListener->release();
184 m_pCommandsListener = NULL;
187 m_xCommandDefinitions = NULL;
188 m_xConnection = NULL;
191 // XServiceInfo
192 //------------------------------------------------------------------------------
193 IMPLEMENT_SERVICE_INFO2(OQueryContainer, "com.sun.star.sdb.dbaccess.OQueryContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDB_QUERIES)
195 // XDataDescriptorFactory
196 //--------------------------------------------------------------------------
197 Reference< XPropertySet > SAL_CALL OQueryContainer::createDataDescriptor( ) throw(RuntimeException)
199 return new OQueryDescriptor();
202 // XAppend
203 //------------------------------------------------------------------------------
204 void SAL_CALL OQueryContainer::appendByDescriptor( const Reference< XPropertySet >& _rxDesc ) throw(SQLException, ElementExistException, RuntimeException)
206 ResettableMutexGuard aGuard(m_aMutex);
207 if ( !m_xCommandDefinitions.is() )
208 throw DisposedException( ::rtl::OUString(), *this );
210 // first clone this object's CommandDefinition part
211 Reference< XPropertySet > xCommandDefinitionPart( m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_QUERYDEFINITION ), UNO_QUERY_THROW );
212 ::comphelper::copyProperties( _rxDesc, xCommandDefinitionPart );
213 // TODO : the columns part of the descriptor has to be copied
215 // create a wrapper for the object (*before* inserting into our command definition container)
216 Reference< XContent > xNewObject( implCreateWrapper( Reference< XContent>( xCommandDefinitionPart, UNO_QUERY_THROW ) ) );
218 ::rtl::OUString sNewObjectName;
219 _rxDesc->getPropertyValue(PROPERTY_NAME) >>= sNewObjectName;
223 notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ApproveListeners );
225 catch( const Exception& )
227 disposeComponent( xNewObject );
228 disposeComponent( xCommandDefinitionPart );
229 throw;
232 // insert the basic object into the definition container
234 m_eDoingCurrently = INSERTING;
235 OAutoActionReset aAutoReset(this);
236 m_xCommandDefinitions->insertByName(sNewObjectName, makeAny(xCommandDefinitionPart));
239 implAppend( sNewObjectName, xNewObject );
240 notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ContainerListemers );
243 // XDrop
244 //------------------------------------------------------------------------------
245 void SAL_CALL OQueryContainer::dropByName( const ::rtl::OUString& _rName ) throw(SQLException, NoSuchElementException, RuntimeException)
247 MutexGuard aGuard(m_aMutex);
248 if ( !checkExistence(_rName) )
249 throw NoSuchElementException(_rName,*this);
251 if ( !m_xCommandDefinitions.is() )
252 throw DisposedException( ::rtl::OUString(), *this );
254 // now simply forward the remove request to the CommandDefinition container, we're a listener for the removal
255 // and thus we do everything neccessary in ::elementRemoved
256 m_xCommandDefinitions->removeByName(_rName);
259 //------------------------------------------------------------------------------
260 void SAL_CALL OQueryContainer::dropByIndex( sal_Int32 _nIndex ) throw(SQLException, IndexOutOfBoundsException, RuntimeException)
262 MutexGuard aGuard(m_aMutex);
263 if ((_nIndex<0) || (_nIndex>getCount()))
264 throw IndexOutOfBoundsException();
266 if ( !m_xCommandDefinitions.is() )
267 throw DisposedException( ::rtl::OUString(), *this );
269 ::rtl::OUString sName;
270 Reference<XPropertySet> xProp(Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getByIndex(_nIndex),UNO_QUERY);
271 if ( xProp.is() )
272 xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
274 dropByName(sName);
276 //------------------------------------------------------------------------------
277 void SAL_CALL OQueryContainer::elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException)
279 Reference< XContent > xNewElement;
280 ::rtl::OUString sElementName;
281 _rEvent.Accessor >>= sElementName;
283 MutexGuard aGuard(m_aMutex);
284 if (INSERTING == m_eDoingCurrently)
285 // nothing to do, we're inserting via an "appendByDescriptor"
286 return;
288 DBG_ASSERT(sElementName.getLength(), "OQueryContainer::elementInserted : invalid name !");
289 DBG_ASSERT(m_aDocumentMap.find(sElementName) == m_aDocumentMap.end(), "OQueryContainer::elementInserted : oops .... we're inconsistent with our master container !");
290 if (!sElementName.getLength() || hasByName(sElementName))
291 return;
293 // insert an own new element
294 xNewElement = implCreateWrapper(sElementName);
296 insertByName(sElementName,makeAny(xNewElement));
299 //------------------------------------------------------------------------------
300 void SAL_CALL OQueryContainer::elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException)
302 ::rtl::OUString sAccessor;
303 _rEvent.Accessor >>= sAccessor;
305 DBG_ASSERT(sAccessor.getLength(), "OQueryContainer::elementRemoved : invalid name !");
306 DBG_ASSERT(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementRemoved : oops .... we're inconsistent with our master container !");
307 if ( !sAccessor.getLength() || !hasByName(sAccessor) )
308 return;
310 removeByName(sAccessor);
313 //------------------------------------------------------------------------------
314 void SAL_CALL OQueryContainer::elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException)
316 Reference< XPropertySet > xReplacedElement;
317 Reference< XContent > xNewElement;
318 ::rtl::OUString sAccessor;
319 _rEvent.Accessor >>= sAccessor;
322 MutexGuard aGuard(m_aMutex);
323 DBG_ASSERT(sAccessor.getLength(), "OQueryContainer::elementReplaced : invalid name !");
324 DBG_ASSERT(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementReplaced : oops .... we're inconsistent with our master container !");
325 if (!sAccessor.getLength() || !hasByName(sAccessor))
326 return;
328 xNewElement = implCreateWrapper(sAccessor);
331 replaceByName(sAccessor,makeAny(xNewElement));
334 //------------------------------------------------------------------------------
335 Reference< XVeto > SAL_CALL OQueryContainer::approveInsertElement( const ContainerEvent& Event ) throw (WrappedTargetException, RuntimeException)
337 ::rtl::OUString sName;
338 OSL_VERIFY( Event.Accessor >>= sName );
339 Reference< XContent > xElement( Event.Element, UNO_QUERY_THROW );
341 Reference< XVeto > xReturn;
344 getElementApproval()->approveElement( sName, xElement.get() );
346 catch( const Exception& )
348 xReturn = new Veto( ::rtl::OUString(), ::cppu::getCaughtException() );
350 return xReturn;
353 //------------------------------------------------------------------------------
354 Reference< XVeto > SAL_CALL OQueryContainer::approveReplaceElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException)
356 return NULL;
359 //------------------------------------------------------------------------------
360 Reference< XVeto > SAL_CALL OQueryContainer::approveRemoveElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException)
362 return NULL;
365 //------------------------------------------------------------------------------
366 void SAL_CALL OQueryContainer::disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw(::com::sun::star::uno::RuntimeException)
368 if (_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinitions, UNO_QUERY).get())
369 { // our "master container" (with the command definitions) is beeing disposed
370 DBG_ERROR("OQueryContainer::disposing : nobody should dispose the CommandDefinition container before disposing my connection !");
371 dispose();
373 else
375 Reference< XContent > xSource(_rSource.Source, UNO_QUERY);
376 // it's one of our documents ....
377 Documents::iterator aIter = m_aDocumentMap.begin();
378 Documents::iterator aEnd = m_aDocumentMap.end();
379 for (;aIter != aEnd;++aIter )
381 if ( xSource == aIter->second.get() )
383 m_xCommandDefinitions->removeByName(aIter->first);
384 break;
387 ODefinitionContainer::disposing(_rSource);
391 // -----------------------------------------------------------------------------
392 ::rtl::OUString OQueryContainer::determineContentType() const
394 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQueryContainer" ) );
397 // -----------------------------------------------------------------------------
398 Reference< XContent > OQueryContainer::implCreateWrapper(const ::rtl::OUString& _rName)
400 Reference< XContent > xObject(m_xCommandDefinitions->getByName(_rName),UNO_QUERY);
401 return implCreateWrapper(xObject);
404 //--------------------------------------------------------------------------
405 Reference< XContent > OQueryContainer::implCreateWrapper(const Reference< XContent >& _rxCommandDesc)
407 Reference<XNameContainer> xContainer(_rxCommandDesc,UNO_QUERY);
408 Reference< XContent > xReturn;
409 if ( xContainer .is() )
411 xReturn = new OQueryContainer( xContainer, m_xConnection, m_aContext.getLegacyServiceFactory(), m_pWarnings );
413 else
415 OQuery* pNewObject = new OQuery( Reference< XPropertySet >( _rxCommandDesc, UNO_QUERY ), m_xConnection, m_aContext.getLegacyServiceFactory() );
416 xReturn = pNewObject;
418 pNewObject->setWarningsContainer( m_pWarnings );
419 // pNewObject->getColumns();
420 // Why? This is expensive. If you comment this in 'cause you really need it, be sure to run the
421 // QueryInQuery test in dbaccess/qa/complex/dbaccess ...
424 return xReturn;
426 //--------------------------------------------------------------------------
427 Reference< XContent > OQueryContainer::createObject( const ::rtl::OUString& _rName)
429 return implCreateWrapper(_rName);
431 // -----------------------------------------------------------------------------
432 sal_Bool OQueryContainer::checkExistence(const ::rtl::OUString& _rName)
434 sal_Bool bRet = sal_False;
435 if ( !m_bInPropertyChange )
437 bRet = m_xCommandDefinitions->hasByName(_rName);
438 Documents::iterator aFind = m_aDocumentMap.find(_rName);
439 if ( !bRet && aFind != m_aDocumentMap.end() )
441 m_aDocuments.erase( ::std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind));
442 m_aDocumentMap.erase(aFind);
444 else if ( bRet && aFind == m_aDocumentMap.end() )
446 implAppend(_rName,NULL);
449 return bRet;
451 //--------------------------------------------------------------------------
452 sal_Bool SAL_CALL OQueryContainer::hasElements( ) throw (RuntimeException)
454 MutexGuard aGuard(m_aMutex);
455 return m_xCommandDefinitions->hasElements();
457 // -----------------------------------------------------------------------------
458 sal_Int32 SAL_CALL OQueryContainer::getCount( ) throw(RuntimeException)
460 MutexGuard aGuard(m_aMutex);
461 return Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getCount();
463 // -----------------------------------------------------------------------------
464 Sequence< ::rtl::OUString > SAL_CALL OQueryContainer::getElementNames( ) throw(RuntimeException)
466 MutexGuard aGuard(m_aMutex);
468 return m_xCommandDefinitions->getElementNames();
471 //........................................................................
472 } // namespace dbaccess
473 //........................................................................