xref: /trunk/main/dbaccess/source/core/api/column.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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