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 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 //-------------------------------------------------------------------------- 88 OColumn::~OColumn() 89 { 90 DBG_DTOR(OColumn, NULL); 91 } 92 93 // com::sun::star::lang::XTypeProvider 94 //-------------------------------------------------------------------------- 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 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 129 void OColumn::disposing() 130 { 131 OPropertyContainer::disposing(); 132 } 133 134 // com::sun::star::beans::XPropertySet 135 //------------------------------------------------------------------------------ 136 Reference< XPropertySetInfo > OColumn::getPropertySetInfo() throw (RuntimeException) 137 { 138 return createPropertySetInfo( getInfoHelper() ) ; 139 } 140 141 // ----------------------------------------------------------------------------- 142 ::rtl::OUString SAL_CALL OColumn::getName( ) throw(::com::sun::star::uno::RuntimeException) 143 { 144 return m_sName; 145 } 146 // ----------------------------------------------------------------------------- 147 void SAL_CALL OColumn::setName( const ::rtl::OUString& _rName ) throw(::com::sun::star::uno::RuntimeException) 148 { 149 m_sName = _rName; 150 } 151 152 // ----------------------------------------------------------------------------- 153 void OColumn::fireValueChange(const ::connectivity::ORowSetValue& /*_rOldValue*/) 154 { 155 DBG_ERROR( "OColumn::fireValueChange: not implemented!" ); 156 } 157 158 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //-------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 223 OColumns::~OColumns() 224 { 225 DBG_DTOR(OColumns, NULL); 226 } 227 228 // XServiceInfo 229 //------------------------------------------------------------------------------ 230 rtl::OUString OColumns::getImplementationName( ) throw(RuntimeException) 231 { 232 return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumns"); 233 } 234 235 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 264 void OColumns::clearColumns() 265 { 266 MutexGuard aGuard(m_rMutex); 267 disposing(); 268 } 269 270 // ----------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 281 void OColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException) 282 { 283 if (m_pRefreshColumns) 284 m_pRefreshColumns->refreshColumns(); 285 } 286 287 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 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 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 466 Reference< XInterface > SAL_CALL OColumns::getParent( ) throw (RuntimeException) 467 { 468 ::osl::MutexGuard aGuard(m_rMutex); 469 return m_xParent; 470 } 471 // ----------------------------------------------------------------------------- 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