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