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