xref: /aoo41x/main/dbaccess/source/core/api/column.cxx (revision cdf0e10c)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #include "ContainerMediator.hxx"
32 #include "apitools.hxx"
33 #include "column.hxx"
34 #include "core_resource.hrc"
35 #include "core_resource.hxx"
36 #include "dbastrings.hrc"
37 #include "sdbcoretools.hxx"
38 
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include <com/sun/star/sdbc/ColumnValue.hpp>
41 #include <com/sun/star/sdbc/DataType.hpp>
42 
43 #include <comphelper/basicio.hxx>
44 #include <comphelper/enumhelper.hxx>
45 #include <comphelper/extract.hxx>
46 #include <comphelper/property.hxx>
47 #include <comphelper/seqstream.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <comphelper/types.hxx>
50 #include <connectivity/TTableHelper.hxx>
51 #include <connectivity/dbexception.hxx>
52 #include <connectivity/dbtools.hxx>
53 #include <cppuhelper/typeprovider.hxx>
54 #include <osl/diagnose.h>
55 #include <tools/debug.hxx>
56 
57 #include <algorithm>
58 
59 using namespace dbaccess;
60 using namespace connectivity;
61 using namespace connectivity;
62 using namespace ::com::sun::star::sdbc;
63 using namespace ::com::sun::star::sdbcx;
64 using namespace ::com::sun::star::beans;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::lang;
67 using namespace ::com::sun::star::awt;
68 using namespace ::com::sun::star::io;
69 using namespace ::com::sun::star::container;
70 using namespace ::com::sun::star::util;
71 using namespace ::osl;
72 using namespace ::comphelper;
73 using namespace ::cppu;
74 
75 DBG_NAME(OColumn)
76 
77 //============================================================
78 //= OColumn
79 //============================================================
80 //--------------------------------------------------------------------------
81 OColumn::OColumn( const bool _bNameIsReadOnly )
82 	    :OColumnBase( m_aMutex )
83         ,::comphelper::OPropertyContainer( OColumnBase::rBHelper )
84 {
85 	DBG_CTOR(OColumn, NULL);
86 
87     registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, _bNameIsReadOnly ? PropertyAttribute::READONLY : 0,
88         &m_sName, ::getCppuType( &m_sName ) );
89 }
90 
91 //--------------------------------------------------------------------------
92 OColumn::~OColumn()
93 {
94 	DBG_DTOR(OColumn, NULL);
95 }
96 
97 // com::sun::star::lang::XTypeProvider
98 //--------------------------------------------------------------------------
99 Sequence< Type > OColumn::getTypes() throw (RuntimeException)
100 {
101 	return ::comphelper::concatSequences(
102 		OColumnBase::getTypes(),
103 		::comphelper::OPropertyContainer::getTypes()
104 	);
105 }
106 
107 // com::sun::star::uno::XInterface
108 IMPLEMENT_FORWARD_XINTERFACE2( OColumn, OColumnBase, ::comphelper::OPropertyContainer )
109 
110 // ::com::sun::star::lang::XServiceInfo
111 //------------------------------------------------------------------------------
112 rtl::OUString OColumn::getImplementationName(  ) throw(RuntimeException)
113 {
114 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumn");
115 }
116 
117 //------------------------------------------------------------------------------
118 sal_Bool OColumn::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
119 {
120 	return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
121 }
122 
123 //------------------------------------------------------------------------------
124 Sequence< ::rtl::OUString > OColumn::getSupportedServiceNames(  ) throw (RuntimeException)
125 {
126 	Sequence< ::rtl::OUString > aSNS( 1 );
127 	aSNS[0] = SERVICE_SDBCX_COLUMN;
128 	return aSNS;
129 }
130 
131 // OComponentHelper
132 //------------------------------------------------------------------------------
133 void OColumn::disposing()
134 {
135 	OPropertyContainer::disposing();
136 }
137 
138 // com::sun::star::beans::XPropertySet
139 //------------------------------------------------------------------------------
140 Reference< XPropertySetInfo > OColumn::getPropertySetInfo() throw (RuntimeException)
141 {
142 	return createPropertySetInfo( getInfoHelper() ) ;
143 }
144 
145 // -----------------------------------------------------------------------------
146 ::rtl::OUString SAL_CALL OColumn::getName(  ) throw(::com::sun::star::uno::RuntimeException)
147 {
148 	return m_sName;
149 }
150 // -----------------------------------------------------------------------------
151 void SAL_CALL OColumn::setName( const ::rtl::OUString& _rName ) throw(::com::sun::star::uno::RuntimeException)
152 {
153 	m_sName = _rName;
154 }
155 
156 // -----------------------------------------------------------------------------
157 void OColumn::fireValueChange(const ::connectivity::ORowSetValue& /*_rOldValue*/)
158 {
159     DBG_ERROR( "OColumn::fireValueChange: not implemented!" );
160 }
161 
162 //------------------------------------------------------------------------------
163 void OColumn::registerProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType )
164 {
165     ::comphelper::OPropertyContainer::registerProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rMemberType );
166 }
167 
168 //------------------------------------------------------------------------------
169 void OColumn::registerMayBeVoidProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, Any* _pPointerToMember, const Type& _rExpectedType )
170 {
171     ::comphelper::OPropertyContainer::registerMayBeVoidProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rExpectedType );
172 }
173 
174 //------------------------------------------------------------------------------
175 void OColumn::registerPropertyNoMember( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, const Type& _rType, const void* _pInitialValue )
176 {
177     ::comphelper::OPropertyContainer::registerPropertyNoMember( _rName, _nHandle, _nAttributes, _rType, _pInitialValue );
178 }
179 
180 //============================================================
181 //= OColumns
182 //============================================================
183 DBG_NAME(OColumns);
184 
185 //--------------------------------------------------------------------------
186 OColumns::OColumns(::cppu::OWeakObject& _rParent,
187 				   ::osl::Mutex& _rMutex,
188 				   sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector,
189 				   IColumnFactory* _pColFactory,
190 				   ::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
191 				   sal_Bool _bAddColumn,
192 				   sal_Bool _bDropColumn,
193 				   sal_Bool _bUseHardRef)
194 				   : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef)
195 	,m_pMediator(NULL)
196 	,m_xDrvColumns(NULL)
197 	,m_pColFactoryImpl(_pColFactory)
198 	,m_pRefreshColumns(_pRefresh)
199 	,m_bInitialized(sal_False)
200 	,m_bAddColumn(_bAddColumn)
201 	,m_bDropColumn(_bDropColumn)
202 {
203 	DBG_CTOR(OColumns, NULL);
204 }
205 
206 // -------------------------------------------------------------------------
207 OColumns::OColumns(::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex,
208 		const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxDrvColumns,
209 		sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector,
210 		IColumnFactory* _pColFactory,
211 		::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
212 		sal_Bool _bAddColumn,
213 		sal_Bool _bDropColumn,
214 		sal_Bool _bUseHardRef)
215 	   : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef)
216 	,m_pMediator(NULL)
217 	,m_xDrvColumns(_rxDrvColumns)
218 	,m_pColFactoryImpl(_pColFactory)
219 	,m_pRefreshColumns(_pRefresh)
220 	,m_bInitialized(sal_False)
221 	,m_bAddColumn(_bAddColumn)
222 	,m_bDropColumn(_bDropColumn)
223 {
224 	DBG_CTOR(OColumns, NULL);
225 }
226 //--------------------------------------------------------------------------
227 OColumns::~OColumns()
228 {
229 	DBG_DTOR(OColumns, NULL);
230 }
231 
232 // XServiceInfo
233 //------------------------------------------------------------------------------
234 rtl::OUString OColumns::getImplementationName(  ) throw(RuntimeException)
235 {
236 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumns");
237 }
238 
239 //------------------------------------------------------------------------------
240 sal_Bool OColumns::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
241 {
242 	return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
243 }
244 
245 //------------------------------------------------------------------------------
246 Sequence< ::rtl::OUString > OColumns::getSupportedServiceNames(  ) throw (RuntimeException)
247 {
248 	Sequence< ::rtl::OUString > aSNS( 1 );
249 	aSNS[0] = SERVICE_SDBCX_CONTAINER;
250 	return aSNS;
251 }
252 
253 //------------------------------------------------------------------
254 void OColumns::append( const ::rtl::OUString& _rName, OColumn* _pColumn )
255 {
256 	MutexGuard aGuard(m_rMutex);
257 
258 	OSL_ENSURE( _pColumn, "OColumns::append: invalid column!" );
259 	OSL_ENSURE( !m_pElements->exists( _rName ),"OColumns::append: Column already exists");
260 
261 	_pColumn->m_sName = _rName;
262 
263 	// now really insert the column
264 	insertElement( _rName, _pColumn );
265 }
266 
267 //------------------------------------------------------------------
268 void OColumns::clearColumns()
269 {
270 	MutexGuard aGuard(m_rMutex);
271 	disposing();
272 }
273 
274 // -----------------------------------------------------------------------------
275 void SAL_CALL OColumns::disposing(void)
276 {
277 	MutexGuard aGuard(m_rMutex);
278 	m_xDrvColumns = NULL;
279 	m_pMediator = NULL;
280 	m_pColFactoryImpl = NULL;
281 	OColumns_BASE::disposing();
282 }
283 
284 // -------------------------------------------------------------------------
285 void OColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException)
286 {
287 	if (m_pRefreshColumns)
288 		m_pRefreshColumns->refreshColumns();
289 }
290 
291 // -------------------------------------------------------------------------
292 connectivity::sdbcx::ObjectType OColumns::createObject(const ::rtl::OUString& _rName)
293 {
294 	OSL_ENSURE(m_pColFactoryImpl, "OColumns::createObject: no column factory!");
295 
296 	connectivity::sdbcx::ObjectType xRet;
297 	if ( m_pColFactoryImpl )
298 	{
299 		xRet = m_pColFactoryImpl->createColumn(_rName);
300 		Reference<XChild> xChild(xRet,UNO_QUERY);
301 		if ( xChild.is() )
302 			xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this)));
303 	}
304 
305 	Reference<XPropertySet> xDest(xRet,UNO_QUERY);
306 	if ( m_pMediator && xDest.is() )
307 		m_pMediator->notifyElementCreated(_rName,xDest);
308 
309 	return xRet;
310 }
311 // -------------------------------------------------------------------------
312 Reference< XPropertySet > OColumns::createDescriptor()
313 {
314 	if ( m_pColFactoryImpl )
315 	{
316 		Reference<XPropertySet> xRet = m_pColFactoryImpl->createColumnDescriptor();
317 		Reference<XChild> xChild(xRet,UNO_QUERY);
318 		if ( xChild.is() )
319 			xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this)));
320 		return xRet;
321 	}
322 	else
323 		return Reference< XPropertySet >();
324 }
325 // -------------------------------------------------------------------------
326 Any SAL_CALL OColumns::queryInterface( const Type & rType ) throw(RuntimeException)
327 {
328 	Any aRet;
329 	if(m_xDrvColumns.is())
330 	{
331 		aRet = m_xDrvColumns->queryInterface(rType);
332 		if ( aRet.hasValue() )
333 			aRet = OColumns_BASE::queryInterface( rType);
334 		if ( !aRet.hasValue() )
335 			aRet = TXChild::queryInterface( rType);
336 		return aRet;
337 	}
338 	else if(!m_pTable || (m_pTable && !m_pTable->isNew()))
339 	{
340 		if(!m_bAddColumn	&& rType == getCppuType( (Reference<XAppend>*)0))
341 			return Any();
342 		if(!m_bDropColumn	&& rType == getCppuType( (Reference<XDrop>*)0))
343 			return Any();
344 	}
345 
346 	aRet = OColumns_BASE::queryInterface( rType);
347 	if ( !aRet.hasValue() )
348 		aRet = TXChild::queryInterface( rType);
349 	return aRet;
350 }
351 // -------------------------------------------------------------------------
352 Sequence< Type > SAL_CALL OColumns::getTypes(  ) throw(RuntimeException)
353 {
354 	sal_Bool bAppendFound = sal_False,bDropFound = sal_False;
355 
356 	sal_Int32 nSize = 0;
357 	Type aAppendType = getCppuType( (Reference<XAppend>*)0);
358 	Type aDropType	 = getCppuType( (Reference<XDrop>*)0);
359 	if(m_xDrvColumns.is())
360 	{
361 		Reference<XTypeProvider> xTypes(m_xDrvColumns,UNO_QUERY);
362 		Sequence< Type > aTypes(xTypes->getTypes());
363 
364 		Sequence< Type > aSecTypes(OColumns_BASE::getTypes());
365 
366 
367 		const Type* pBegin = aTypes.getConstArray();
368 		const Type* pEnd = pBegin + aTypes.getLength();
369 		for (;pBegin != pEnd ; ++pBegin)
370 		{
371 			if(aAppendType == *pBegin)
372 				bAppendFound = sal_True;
373 			else if(aDropType == *pBegin)
374 				bDropFound = sal_True;
375 		}
376 		nSize = (bDropFound ? (bAppendFound ? 0 : 1) : (bAppendFound ? 1 : 2));
377 	}
378 	else
379 	{
380 		nSize = ((m_pTable && m_pTable->isNew()) ? 0 :
381 					((m_bDropColumn ?
382 						(m_bAddColumn ? 0 : 1) : (m_bAddColumn ? 1 : 2))));
383 		bDropFound		= (m_pTable && m_pTable->isNew()) || m_bDropColumn;
384 		bAppendFound	= (m_pTable && m_pTable->isNew()) || m_bAddColumn;
385 	}
386 	Sequence< Type > aTypes(::comphelper::concatSequences(OColumns_BASE::getTypes(),TXChild::getTypes()));
387 	Sequence< Type > aRet(aTypes.getLength() - nSize);
388 
389 	const Type* pBegin = aTypes.getConstArray();
390 	const Type* pEnd = pBegin + aTypes.getLength();
391 	for(sal_Int32 i=0;pBegin != pEnd ;++pBegin)
392 	{
393 		if(*pBegin != aAppendType && *pBegin != aDropType)
394 			aRet.getArray()[i++] = *pBegin;
395 		else if(bDropFound && *pBegin == aDropType)
396 			aRet.getArray()[i++] = *pBegin;
397 		else if(bAppendFound && *pBegin == aAppendType)
398 			aRet.getArray()[i++] = *pBegin;
399 	}
400 	return aRet;
401 }
402 // -------------------------------------------------------------------------
403 // XAppend
404 sdbcx::ObjectType OColumns::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor )
405 {
406     sdbcx::ObjectType xReturn;
407 
408     Reference< XAppend > xAppend( m_xDrvColumns, UNO_QUERY );
409 	if ( xAppend.is() )
410 	{
411 		xAppend->appendByDescriptor(descriptor);
412         xReturn = createObject( _rForName );
413 	}
414     else if ( m_pTable && !m_pTable->isNew() )
415     {
416         if ( m_bAddColumn )
417         {
418             Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService();
419             if ( xAlterService.is() )
420             {
421                 xAlterService->addColumn(m_pTable,descriptor);
422                 xReturn = createObject( _rForName );
423             }
424             else
425                 xReturn = OColumns_BASE::appendObject( _rForName, descriptor );
426         }
427         else
428             ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_ADD ), static_cast<XChild*>(static_cast<TXChild*>(this)) );
429     }
430     else
431         xReturn = cloneDescriptor( descriptor );
432 
433     if ( m_pColFactoryImpl )
434 		m_pColFactoryImpl->columnAppended( descriptor );
435 
436     ::dbaccess::notifyDataSourceModified(m_xParent,sal_True);
437 
438     return xReturn;
439 }
440 // -------------------------------------------------------------------------
441 // XDrop
442 void OColumns::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName)
443 {
444 	Reference< XDrop > xDrop( m_xDrvColumns, UNO_QUERY );
445 	if ( xDrop.is() )
446 	{
447 		xDrop->dropByName( _sElementName );
448 	}
449 	else if ( m_pTable && !m_pTable->isNew() )
450     {
451         if ( m_bDropColumn )
452         {
453             Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService();
454             if ( xAlterService.is() )
455                 xAlterService->dropColumn(m_pTable,_sElementName);
456             else
457 		        OColumns_BASE::dropObject(_nPos,_sElementName);
458         }
459         else
460             ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_DROP ), static_cast<XChild*>(static_cast<TXChild*>(this)) );
461     }
462 
463     if ( m_pColFactoryImpl )
464 		m_pColFactoryImpl->columnDropped(_sElementName);
465 
466     ::dbaccess::notifyDataSourceModified(m_xParent,sal_True);
467 }
468 // -----------------------------------------------------------------------------
469 
470 Reference< XInterface > SAL_CALL OColumns::getParent(  ) throw (RuntimeException)
471 {
472 	::osl::MutexGuard aGuard(m_rMutex);
473 	return m_xParent;
474 }
475 // -----------------------------------------------------------------------------
476 void SAL_CALL OColumns::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException)
477 {
478 	::osl::MutexGuard aGuard(m_rMutex);
479 	m_xParent = _xParent;
480 }
481 // -----------------------------------------------------------------------------
482