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_connectivity.hxx" 30 #include "connectivity/parameters.hxx" 31 32 /** === begin UNO includes === **/ 33 #include <com/sun/star/form/DatabaseParameterEvent.hpp> 34 #include <com/sun/star/sdbc/XParameters.hpp> 35 #include <com/sun/star/container/XChild.hpp> 36 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 37 #include <com/sun/star/container/XEnumerationAccess.hpp> 38 #include <com/sun/star/sdb/XParametersSupplier.hpp> 39 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp> 40 #include <com/sun/star/sdb/ParametersRequest.hpp> 41 /** === end UNO includes === **/ 42 43 #include <connectivity/dbtools.hxx> 44 #include "connectivity/filtermanager.hxx" 45 #include "TConnection.hxx" 46 47 #include <tools/debug.hxx> 48 #include <tools/diagnose_ex.h> 49 50 #include <comphelper/uno3.hxx> 51 #include <comphelper/proparrhlp.hxx> 52 #include <comphelper/broadcasthelper.hxx> 53 #include "connectivity/ParameterCont.hxx" 54 #include <rtl/ustrbuf.hxx> 55 56 //........................................................................ 57 namespace dbtools 58 { 59 //........................................................................ 60 61 using namespace ::com::sun::star::uno; 62 using namespace ::com::sun::star::sdb; 63 using namespace ::com::sun::star::sdbc; 64 using namespace ::com::sun::star::sdbcx; 65 using namespace ::com::sun::star::lang; 66 using namespace ::com::sun::star::beans; 67 using namespace ::com::sun::star::task; 68 using namespace ::com::sun::star::form; 69 using namespace ::com::sun::star::container; 70 71 using namespace ::comphelper; 72 using namespace ::connectivity; 73 74 //==================================================================== 75 //= ParameterManager 76 //==================================================================== 77 //-------------------------------------------------------------------- 78 ParameterManager::ParameterManager( ::osl::Mutex& _rMutex, const Reference< XMultiServiceFactory >& _rxORB ) 79 :m_rMutex ( _rMutex ) 80 ,m_aParameterListeners( _rMutex ) 81 ,m_xORB ( _rxORB ) 82 ,m_pOuterParameters ( NULL ) 83 ,m_nInnerCount ( 0 ) 84 ,m_bUpToDate ( false ) 85 { 86 OSL_ENSURE( m_xORB.is(), "ParameterManager::ParameterManager: no service factory!" ); 87 } 88 89 //-------------------------------------------------------------------- 90 void ParameterManager::initialize( const Reference< XPropertySet >& _rxComponent, const Reference< XAggregation >& _rxComponentAggregate ) 91 { 92 OSL_ENSURE( !m_xComponent.get().is(), "ParameterManager::initialize: already initialized!" ); 93 94 m_xComponent = _rxComponent; 95 m_xAggregatedRowSet = _rxComponentAggregate; 96 if ( m_xAggregatedRowSet.is() ) 97 m_xAggregatedRowSet->queryAggregation( ::getCppuType( &m_xInnerParamUpdate ) ) >>= m_xInnerParamUpdate; 98 OSL_ENSURE( m_xComponent.get().is() && m_xInnerParamUpdate.is(), "ParameterManager::initialize: invalid arguments!" ); 99 if ( !m_xComponent.get().is() || !m_xInnerParamUpdate.is() ) 100 return; 101 } 102 103 //-------------------------------------------------------------------- 104 void ParameterManager::dispose( ) 105 { 106 clearAllParameterInformation(); 107 108 m_xComposer.clear(); 109 m_xParentComposer.clear(); 110 //m_xComponent.clear(); 111 m_xInnerParamUpdate.clear(); 112 m_xAggregatedRowSet.clear(); 113 } 114 115 //-------------------------------------------------------------------- 116 void ParameterManager::clearAllParameterInformation() 117 { 118 m_xInnerParamColumns.clear(); 119 if ( m_pOuterParameters.is() ) 120 m_pOuterParameters->dispose(); 121 m_pOuterParameters = NULL; 122 m_nInnerCount = 0; 123 ParameterInformation aEmptyInfo; 124 m_aParameterInformation.swap( aEmptyInfo ); 125 m_aMasterFields.realloc( 0 ); 126 m_aDetailFields.realloc( 0 ); 127 m_sIdentifierQuoteString = ::rtl::OUString(); 128 ::std::vector< bool > aEmptyArray; 129 m_aParametersVisited.swap( aEmptyArray ); 130 m_bUpToDate = false; 131 } 132 133 //-------------------------------------------------------------------- 134 void ParameterManager::disposing( const EventObject& /*_rDisposingEvent*/ ) 135 { 136 } 137 138 //-------------------------------------------------------------------- 139 void ParameterManager::setAllParametersNull() SAL_THROW( ( SQLException, RuntimeException ) ) 140 { 141 OSL_PRECOND( isAlive(), "ParameterManager::setAllParametersNull: not initialized, or already disposed!" ); 142 if ( !isAlive() ) 143 return; 144 145 for ( sal_Int32 i = 1; i <= m_nInnerCount; ++i ) 146 m_xInnerParamUpdate->setNull( i, DataType::VARCHAR ); 147 } 148 149 //-------------------------------------------------------------------- 150 bool ParameterManager::initializeComposerByComponent( const Reference< XPropertySet >& _rxComponent ) 151 { 152 OSL_PRECOND( _rxComponent.is(), "ParameterManager::initializeComposerByComponent: invalid !" ); 153 154 m_xComposer.clear(); 155 m_xInnerParamColumns.clear(); 156 m_nInnerCount = 0; 157 158 // create and fill a composer 159 try 160 { 161 // get a query composer for the 's settings 162 m_xComposer.reset( getCurrentSettingsComposer( _rxComponent, m_xORB ), SharedQueryComposer::TakeOwnership ); 163 164 // see if the composer found parameters 165 Reference< XParametersSupplier > xParamSupp( m_xComposer, UNO_QUERY ); 166 if ( xParamSupp.is() ) 167 m_xInnerParamColumns = xParamSupp->getParameters(); 168 169 if ( m_xInnerParamColumns.is() ) 170 m_nInnerCount = m_xInnerParamColumns->getCount(); 171 } 172 catch( const SQLException& ) 173 { 174 } 175 176 return m_xInnerParamColumns.is(); 177 } 178 179 //-------------------------------------------------------------------- 180 void ParameterManager::collectInnerParameters( bool _bSecondRun ) 181 { 182 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::collectInnerParameters: missing some internal data!" ); 183 if ( !m_xInnerParamColumns.is() ) 184 return; 185 186 // strip previous index informations 187 if ( _bSecondRun ) 188 { 189 for ( ParameterInformation::iterator aParamInfo = m_aParameterInformation.begin(); 190 aParamInfo != m_aParameterInformation.end(); 191 ++aParamInfo 192 ) 193 { 194 aParamInfo->second.aInnerIndexes.clear(); 195 } 196 } 197 198 // we need to map the parameter names (which is all we get from the 's 199 // MasterFields property) to indicies, which are needed by the XParameters 200 // interface of the row set) 201 Reference<XPropertySet> xParam; 202 for ( sal_Int32 i = 0; i < m_nInnerCount; ++i ) 203 { 204 try 205 { 206 xParam.clear(); 207 m_xInnerParamColumns->getByIndex( i ) >>= xParam; 208 209 ::rtl::OUString sName; 210 xParam->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName; 211 212 // only append additonal paramters when they are not already in the list 213 ParameterInformation::iterator aExistentPos = m_aParameterInformation.find( sName ); 214 OSL_ENSURE( !_bSecondRun || ( aExistentPos != m_aParameterInformation.end() ), 215 "ParameterManager::collectInnerParameters: the parameter information should already exist in the second run!" ); 216 217 if ( aExistentPos == m_aParameterInformation.end() ) 218 { 219 aExistentPos = m_aParameterInformation.insert( ParameterInformation::value_type( 220 sName, xParam ) ).first; 221 } 222 else 223 aExistentPos->second.xComposerColumn = xParam; 224 225 aExistentPos->second.aInnerIndexes.push_back( i ); 226 } 227 catch( const Exception& ) 228 { 229 OSL_ENSURE( sal_False, "ParameterManager::collectInnerParameters: caught an exception!" ); 230 } 231 } 232 } 233 234 //-------------------------------------------------------------------- 235 ::rtl::OUString ParameterManager::createFilterConditionFromColumnLink( 236 const ::rtl::OUString& _rMasterColumn, const ::rtl::OUString& _rDetailLink, ::rtl::OUString& _rNewParamName ) 237 { 238 ::rtl::OUString sFilter; 239 240 // format is: 241 // <detail_column> = :<new_param_name> 242 sFilter = quoteName( m_sIdentifierQuoteString, _rDetailLink ); 243 sFilter += ::rtl::OUString::createFromAscii( " = :" ); 244 245 // generate a parameter name which is not already used 246 _rNewParamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "link_from_" ) ); 247 _rNewParamName += convertName2SQLName( _rMasterColumn, m_sSpecialCharacters ); 248 while ( m_aParameterInformation.find( _rNewParamName ) != m_aParameterInformation.end() ) 249 { 250 _rNewParamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_" ) ); 251 } 252 253 return sFilter += _rNewParamName; 254 } 255 256 //-------------------------------------------------------------------- 257 void ParameterManager::classifyLinks( const Reference< XNameAccess >& _rxParentColumns, 258 const Reference< XNameAccess >& _rxColumns, ::std::vector< ::rtl::OUString >& _out_rAdditionalFilterComponents ) SAL_THROW(( Exception )) 259 { 260 OSL_PRECOND( m_aMasterFields.getLength() == m_aDetailFields.getLength(), 261 "ParameterManager::classifyLinks: master and detail fields should have the same length!" ); 262 OSL_ENSURE( _rxColumns.is(), "ParameterManager::classifyLinks: invalid columns!" ); 263 264 if ( !_rxColumns.is() ) 265 return; 266 267 // we may need to strip any links which are invalid, so here go the containers 268 // for temporarirly holding the new pairs 269 ::std::vector< ::rtl::OUString > aStrippedMasterFields; 270 ::std::vector< ::rtl::OUString > aStrippedDetailFields; 271 272 bool bNeedExchangeLinks = false; 273 274 // classify the links 275 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray(); 276 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray(); 277 const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength(); 278 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields ) 279 { 280 if ( !pMasterFields->getLength() || !pDetailFields->getLength() ) 281 continue; 282 283 // if not even the master part of the relationship exists in the parent , the 284 // link is invalid as a whole 285 // #i63674# / 2006-03-28 / frank.schoenheit@sun.com 286 if ( !_rxParentColumns->hasByName( *pMasterFields ) ) 287 { 288 bNeedExchangeLinks = true; 289 continue; 290 } 291 292 bool bValidLink = true; 293 294 // is there an inner parameter with this name? That is, a parameter which is already part of 295 // the very original statement (not the one we create ourselve, with the additional parameters) 296 ParameterInformation::iterator aPos = m_aParameterInformation.find( *pDetailFields ); 297 if ( aPos != m_aParameterInformation.end() ) 298 { // there is an inner parameter with this name 299 aPos->second.eType = eLinkedByParamName; 300 aStrippedDetailFields.push_back( *pDetailFields ); 301 } 302 else 303 { 304 // does the detail name denote a column? 305 if ( _rxColumns->hasByName( *pDetailFields ) ) 306 { 307 ::rtl::OUString sNewParamName; 308 const ::rtl::OUString sFilterCondition = createFilterConditionFromColumnLink( *pMasterFields, *pDetailFields, sNewParamName ); 309 OSL_PRECOND( sNewParamName.getLength(), "ParameterManager::classifyLinks: createFilterConditionFromColumnLink returned nonsense!" ); 310 311 // remember meta information about this new parameter 312 ::std::pair< ParameterInformation::iterator, bool > aInsertionPos = 313 m_aParameterInformation.insert( 314 ParameterInformation::value_type( sNewParamName, ParameterMetaData( NULL ) ) 315 ); 316 OSL_ENSURE( aInsertionPos.second, "ParameterManager::classifyLinks: there already was a parameter with this name!" ); 317 aInsertionPos.first->second.eType = eLinkedByColumnName; 318 319 // remember the filter component 320 _out_rAdditionalFilterComponents.push_back( sFilterCondition ); 321 322 // remember the new "detail field" for this link 323 aStrippedDetailFields.push_back( sNewParamName ); 324 bNeedExchangeLinks = true; 325 } 326 else 327 { 328 // the detail field neither denotes a column name, nor a parameter name 329 bValidLink = false; 330 bNeedExchangeLinks = true; 331 } 332 } 333 334 if ( bValidLink ) 335 aStrippedMasterFields.push_back( *pMasterFields ); 336 } 337 OSL_POSTCOND( aStrippedMasterFields.size() == aStrippedDetailFields.size(), 338 "ParameterManager::classifyLinks: inconsistency in new link pairs!" ); 339 340 if ( bNeedExchangeLinks ) 341 { 342 ::rtl::OUString *pFields = aStrippedMasterFields.empty() ? 0 : &aStrippedMasterFields[0]; 343 m_aMasterFields = Sequence< ::rtl::OUString >( pFields, aStrippedMasterFields.size() ); 344 pFields = aStrippedDetailFields.empty() ? 0 : &aStrippedDetailFields[0]; 345 m_aDetailFields = Sequence< ::rtl::OUString >( pFields, aStrippedDetailFields.size() ); 346 } 347 } 348 349 //-------------------------------------------------------------------- 350 void ParameterManager::analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails ) 351 { 352 OSL_PRECOND( isAlive(), "ParameterManager::analyzeFieldLinks: not initialized, or already disposed!" ); 353 if ( !isAlive() ) 354 return; 355 356 _rColumnsInLinkDetails = false; 357 try 358 { 359 // the links as determined by the properties 360 Reference< XPropertySet > xProp = m_xComponent; 361 OSL_ENSURE(xProp.is(),"Some already released my component!"); 362 if ( xProp.is() ) 363 { 364 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MASTERFIELDS) ) >>= m_aMasterFields; 365 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DETAILFIELDS) ) >>= m_aDetailFields; 366 } 367 368 { 369 // normalize to equal length 370 sal_Int32 nMasterLength = m_aMasterFields.getLength(); 371 sal_Int32 nDetailLength = m_aDetailFields.getLength(); 372 373 if ( nMasterLength > nDetailLength ) 374 m_aMasterFields.realloc( nDetailLength ); 375 else if ( nDetailLength > nMasterLength ) 376 m_aDetailFields.realloc( nMasterLength ); 377 } 378 379 Reference< XNameAccess > xColumns; 380 if ( !getColumns( xColumns, true ) ) 381 // already asserted in getColumns 382 return; 383 384 Reference< XNameAccess > xParentColumns; 385 if ( !getParentColumns( xParentColumns, true ) ) 386 return; 387 388 // classify the links - depending on what the detail fields in each link pair denotes 389 ::std::vector< ::rtl::OUString > aAdditionalFilterComponents; 390 classifyLinks( xParentColumns, xColumns, aAdditionalFilterComponents ); 391 392 // did we find links where the detail field refers to a detail column (instead of a parameter name)? 393 if ( !aAdditionalFilterComponents.empty() ) 394 { 395 const static ::rtl::OUString s_sAnd( RTL_CONSTASCII_USTRINGPARAM( " AND " ) ); 396 // build a conjunction of all the filter components 397 ::rtl::OUStringBuffer sAdditionalFilter; 398 for ( ::std::vector< ::rtl::OUString >::const_iterator aComponent = aAdditionalFilterComponents.begin(); 399 aComponent != aAdditionalFilterComponents.end(); 400 ++aComponent 401 ) 402 { 403 if ( sAdditionalFilter.getLength() ) 404 sAdditionalFilter.append(s_sAnd); 405 406 sAdditionalFilter.appendAscii("( ",((sal_Int32)(sizeof("( ")-1))); 407 sAdditionalFilter.append(*aComponent); 408 sAdditionalFilter.appendAscii(" )",((sal_Int32)(sizeof(" )")-1))); 409 } 410 411 // now set this filter at the 's filter manager 412 _rFilterManager.setFilterComponent( FilterManager::fcLinkFilter, sAdditionalFilter.makeStringAndClear() ); 413 414 _rColumnsInLinkDetails = true; 415 } 416 } 417 catch( const Exception& ) 418 { 419 OSL_ENSURE( sal_False, "ParameterManager::analyzeFieldLinks: caught an exception!" ); 420 } 421 } 422 423 //-------------------------------------------------------------------- 424 void ParameterManager::createOuterParameters() 425 { 426 OSL_PRECOND( !m_pOuterParameters.is(), "ParameterManager::createOuterParameters: outer parameters not initialized!" ); 427 OSL_PRECOND( m_xInnerParamUpdate.is(), "ParameterManager::createOuterParameters: no write access to the inner parameters!" ); 428 if ( !m_xInnerParamUpdate.is() ) 429 return; 430 431 m_pOuterParameters = new param::ParameterWrapperContainer; 432 433 #if OSL_DEBUG_LEVEL > 0 434 sal_Int32 nSmallestIndexLinkedByColumnName = -1; 435 sal_Int32 nLargestIndexNotLinkedByColumnName = -1; 436 #endif 437 ::rtl::OUString sName; 438 for ( ParameterInformation::iterator aParam = m_aParameterInformation.begin(); 439 aParam != m_aParameterInformation.end(); 440 ++aParam 441 ) 442 { 443 #if OSL_DEBUG_LEVEL > 0 444 if ( aParam->second.aInnerIndexes.size() ) 445 if ( aParam->second.eType == eLinkedByColumnName ) 446 { 447 if ( nSmallestIndexLinkedByColumnName == -1 ) 448 nSmallestIndexLinkedByColumnName = aParam->second.aInnerIndexes[ 0 ]; 449 } 450 else 451 { 452 nLargestIndexNotLinkedByColumnName = aParam->second.aInnerIndexes[ aParam->second.aInnerIndexes.size() - 1 ]; 453 } 454 #endif 455 if ( aParam->second.eType != eFilledExternally ) 456 continue; 457 458 // check which of the parameters have already been visited (e.g. filled via XParameters) 459 size_t nAlreadyVisited = 0; 460 for ( ::std::vector< sal_Int32 >::iterator aIndex = aParam->second.aInnerIndexes.begin(); 461 aIndex != aParam->second.aInnerIndexes.end(); 462 ++aIndex 463 ) 464 { 465 if ( ( m_aParametersVisited.size() > (size_t)*aIndex ) && m_aParametersVisited[ *aIndex ] ) 466 { // exclude this index 467 *aIndex = -1; 468 ++nAlreadyVisited; 469 } 470 } 471 if ( nAlreadyVisited == aParam->second.aInnerIndexes.size() ) 472 continue; 473 474 // need a wrapper for this .... the "inner parameters" as supplied by a result set don't have a "Value" 475 // property, but the parameter listeners expect such a property. So we need an object "aggregating" 476 // xParam and supplying an additional property ("Value") 477 // (it's no real aggregation of course ...) 478 m_pOuterParameters->push_back( new param::ParameterWrapper( aParam->second.xComposerColumn, m_xInnerParamUpdate, aParam->second.aInnerIndexes ) ); 479 } 480 481 #if OSL_DEBUG_LEVEL > 0 482 OSL_ENSURE( ( nSmallestIndexLinkedByColumnName == -1 ) || ( nLargestIndexNotLinkedByColumnName == -1 ) || 483 ( nSmallestIndexLinkedByColumnName > nLargestIndexNotLinkedByColumnName ), 484 "ParameterManager::createOuterParameters: inconsistency!" ); 485 486 // for the master-detail links, where the detail field denoted a column name, we created an addtional ("artificial") 487 // filter, and *appended* it to all other (potentially) existing filters of the row set. This means that the indexes 488 // for the parameters resulting from the artifical filter should be larger than any other parameter index, and this 489 // is what the assertion checks. 490 // If the assertion fails, then we would need another handling for the "parameters visited" flags, since they're based 491 // on parameter indexes *without* the artificial filter (because this filter is not visible from the outside). 492 #endif 493 } 494 495 //-------------------------------------------------------------------- 496 void ParameterManager::updateParameterInfo( FilterManager& _rFilterManager ) 497 { 498 OSL_PRECOND( isAlive(), "ParameterManager::updateParameterInfo: not initialized, or already disposed!" ); 499 if ( !isAlive() ) 500 return; 501 502 clearAllParameterInformation(); 503 cacheConnectionInfo(); 504 505 // check whether the is based on a statement/query which requires parameters 506 Reference< XPropertySet > xProp = m_xComponent; 507 OSL_ENSURE(xProp.is(),"Some already released my component!"); 508 if ( xProp.is() ) 509 { 510 if ( !initializeComposerByComponent( xProp ) ) 511 { // okay, nothing to do 512 m_bUpToDate = true; 513 return; 514 } // if ( !initializeComposerByComponent( m_xComponent ) ) 515 } 516 OSL_POSTCOND( m_xInnerParamColumns.is(), "ParameterManager::updateParameterInfo: initializeComposerByComponent did nonsense (1)!" ); 517 518 // collect all parameters which are defined by the "inner parameters" 519 collectInnerParameters( false ); 520 521 // analyze the master-detail relationships 522 bool bColumnsInLinkDetails = false; 523 analyzeFieldLinks( _rFilterManager, bColumnsInLinkDetails ); 524 525 if ( bColumnsInLinkDetails ) 526 { 527 // okay, in this case, analyzeFieldLinks modified the "real" filter at the RowSet, to contain 528 // an additional restriction (which we created ourself) 529 // So we need to update all information about our inner parameter columns 530 Reference< XPropertySet > xDirectRowSetProps; 531 m_xAggregatedRowSet->queryAggregation( ::getCppuType( &xDirectRowSetProps ) ) >>= xDirectRowSetProps; 532 OSL_VERIFY( initializeComposerByComponent( xDirectRowSetProps ) ); 533 collectInnerParameters( true ); 534 } 535 536 if ( !m_nInnerCount ) 537 { // no parameters at all 538 m_bUpToDate = true; 539 return; 540 } 541 542 // for what now remains as outer parameters, create the wrappers for the single 543 // parameter columns 544 createOuterParameters(); 545 546 m_bUpToDate = true; 547 } 548 549 //-------------------------------------------------------------------- 550 void ParameterManager::fillLinkedParameters( const Reference< XNameAccess >& _rxParentColumns ) 551 { 552 OSL_PRECOND( isAlive(), "ParameterManager::fillLinkedParameters: not initialized, or already disposed!" ); 553 if ( !isAlive() ) 554 return; 555 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::fillLinkedParameters: no inner parameters found!" ); 556 OSL_ENSURE ( _rxParentColumns.is(), "ParameterManager::fillLinkedParameters: invalid parent columns!" ); 557 558 try 559 { 560 // the master and detail field( name)s of the 561 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray(); 562 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray(); 563 564 sal_Int32 nMasterLen = m_aMasterFields.getLength(); 565 Any aParamType, aScale, aValue; 566 567 // loop through all master fields. For each of them, get the respective column from the 568 // parent , and forward it's current value as paramter value to the (inner) row set 569 for ( sal_Int32 i = 0; i < nMasterLen; ++i, ++pMasterFields, ++pDetailFields ) 570 { 571 // does the name denote a valid column in the parent? 572 if ( !_rxParentColumns->hasByName( *pMasterFields ) ) 573 { 574 OSL_ENSURE( sal_False, "ParameterManager::fillLinkedParameters: invalid master names should have been stripped long before!" ); 575 continue; 576 } 577 578 // do we, for this name, know where to place the values? 579 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields ); 580 if ( ( aParamInfo == m_aParameterInformation.end() ) 581 || ( aParamInfo->second.aInnerIndexes.empty() ) 582 ) 583 { 584 OSL_ENSURE( sal_False, "ParameterManager::fillLinkedParameters: nothing known about this detail field!" ); 585 continue; 586 } 587 588 // the concrete master field 589 Reference< XPropertySet > xMasterField(_rxParentColumns->getByName( *pMasterFields ),UNO_QUERY); 590 591 // the positions where we have to fill in values for the current parameter name 592 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin(); 593 aPosition != aParamInfo->second.aInnerIndexes.end(); 594 ++aPosition 595 ) 596 { 597 // the concrete detail field 598 Reference< XPropertySet > xDetailField(m_xInnerParamColumns->getByIndex( *aPosition ),UNO_QUERY); 599 OSL_ENSURE( xDetailField.is(), "ParameterManager::fillLinkedParameters: invalid detail field!" ); 600 if ( !xDetailField.is() ) 601 continue; 602 603 // type and scale of the parameter field 604 sal_Int32 nParamType = DataType::VARCHAR; 605 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nParamType ); 606 607 sal_Int32 nScale = 0; 608 if ( xDetailField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) ) 609 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) >>= nScale ); 610 611 // transfer the param value 612 try 613 { 614 m_xInnerParamUpdate->setObjectWithInfo( 615 *aPosition + 1, // parameters are based at 1 616 xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ), 617 nParamType, 618 nScale 619 ); 620 } 621 catch( const Exception& ) 622 { 623 OSL_ENSURE( sal_False, 624 ::rtl::OString( "ParameterManager::fillLinkedParameters: master-detail parameter number " ) 625 += ::rtl::OString::valueOf( sal_Int32( *aPosition + 1 ) ) 626 += ::rtl::OString( " could not be filled!" ) ); 627 } 628 } 629 } 630 } 631 catch( const Exception& ) 632 { 633 DBG_UNHANDLED_EXCEPTION(); 634 } 635 } 636 637 //-------------------------------------------------------------------- 638 bool ParameterManager::completeParameters( const Reference< XInteractionHandler >& _rxCompletionHandler, const Reference< XConnection > _rxConnection ) 639 { 640 OSL_PRECOND( isAlive(), "ParameterManager::completeParameters: not initialized, or already disposed!" ); 641 OSL_ENSURE ( _rxCompletionHandler.is(), "ParameterManager::completeParameters: invalid interaction handler!" ); 642 643 // two continuations (Ok and Cancel) 644 OInteractionAbort* pAbort = new OInteractionAbort; 645 OParameterContinuation* pParams = new OParameterContinuation; 646 647 // the request 648 ParametersRequest aRequest; 649 aRequest.Parameters = m_pOuterParameters.get(); 650 aRequest.Connection = _rxConnection; 651 OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aRequest ) ); 652 Reference< XInteractionRequest > xRequest( pRequest ); 653 654 // some knittings 655 pRequest->addContinuation( pAbort ); 656 pRequest->addContinuation( pParams ); 657 658 // execute the request 659 try 660 { 661 _rxCompletionHandler->handle( xRequest ); 662 } 663 catch( const Exception& ) 664 { 665 OSL_ENSURE( sal_False, "ParameterManager::completeParameters: caught an exception while calling the handler!" ); 666 } 667 668 if ( !pParams->wasSelected() ) 669 // canceled by the user (i.e. (s)he canceled the dialog) 670 return false; 671 672 try 673 { 674 // transfer the values from the continuation object to the parameter columns 675 Sequence< PropertyValue > aFinalValues = pParams->getValues(); 676 const PropertyValue* pFinalValues = aFinalValues.getConstArray(); 677 for ( sal_Int32 i = 0; i < aFinalValues.getLength(); ++i, ++pFinalValues ) 678 { 679 Reference< XPropertySet > xParamColumn(aRequest.Parameters->getByIndex( i ),UNO_QUERY); 680 if ( xParamColumn.is() ) 681 { 682 #ifdef DBG_UTIL 683 ::rtl::OUString sName; 684 xParamColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName; 685 OSL_ENSURE( sName == pFinalValues->Name, "ParameterManager::completeParameters: inconsistent parameter names!" ); 686 #endif 687 xParamColumn->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), pFinalValues->Value ); 688 // the property sets are wrapper classes, translating the Value property into a call to 689 // the appropriate XParameters interface 690 } 691 } 692 } 693 catch( const Exception& ) 694 { 695 OSL_ENSURE( sal_False, "ParameterManager::completeParameters: caught an exception while propagating the values!" ); 696 } 697 return true; 698 } 699 700 //-------------------------------------------------------------------- 701 bool ParameterManager::consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies ) 702 { 703 bool bCanceled = false; 704 705 sal_Int32 nParamsLeft = m_pOuterParameters->getParameters().size(); 706 // TODO: shouldn't we subtract all the parameters which were already visited? 707 if ( nParamsLeft ) 708 { 709 ::cppu::OInterfaceIteratorHelper aIter( m_aParameterListeners ); 710 Reference< XPropertySet > xProp = m_xComponent; 711 OSL_ENSURE(xProp.is(),"Some already released my component!"); 712 DatabaseParameterEvent aEvent( xProp.get(), m_pOuterParameters.get() ); 713 714 _rClearForNotifies.clear(); 715 while ( aIter.hasMoreElements() && !bCanceled ) 716 bCanceled = !static_cast< XDatabaseParameterListener* >( aIter.next() )->approveParameter( aEvent ); 717 _rClearForNotifies.reset(); 718 } 719 720 return !bCanceled; 721 } 722 723 //-------------------------------------------------------------------- 724 bool ParameterManager::fillParameterValues( const Reference< XInteractionHandler >& _rxCompletionHandler, ::osl::ResettableMutexGuard& _rClearForNotifies ) 725 { 726 OSL_PRECOND( isAlive(), "ParameterManager::fillParameterValues: not initialized, or already disposed!" ); 727 if ( !isAlive() ) 728 return true; 729 730 if ( m_nInnerCount == 0 ) 731 // no parameters at all 732 return true; 733 734 // fill the parameters from the master-detail relationship 735 Reference< XNameAccess > xParentColumns; 736 if ( getParentColumns( xParentColumns, false ) && xParentColumns->hasElements() && m_aMasterFields.getLength() ) 737 fillLinkedParameters( xParentColumns ); 738 739 // let the user (via the interaction handler) fill all remaining parameters 740 Reference< XConnection > xConnection; 741 getConnection( xConnection ); 742 743 if ( _rxCompletionHandler.is() ) 744 return completeParameters( _rxCompletionHandler, xConnection ); 745 746 return consultParameterListeners( _rClearForNotifies ); 747 } 748 749 //-------------------------------------------------------------------- 750 bool ParameterManager::getConnection( Reference< XConnection >& /* [out] */ _rxConnection ) 751 { 752 OSL_PRECOND( isAlive(), "ParameterManager::getConnection: not initialized, or already disposed!" ); 753 if ( !isAlive() ) 754 return false; 755 756 _rxConnection.clear(); 757 try 758 { 759 Reference< XPropertySet > xProp = m_xComponent; 760 OSL_ENSURE(xProp.is(),"Some already released my component!"); 761 if ( xProp.is() ) 762 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ACTIVE_CONNECTION) ) >>= _rxConnection; 763 } 764 catch( const Exception& ) 765 { 766 OSL_ENSURE( sal_False, "ParameterManager::getConnection: could not retrieve the connection of the !" ); 767 } 768 return _rxConnection.is(); 769 } 770 771 //-------------------------------------------------------------------- 772 void ParameterManager::cacheConnectionInfo() SAL_THROW(( )) 773 { 774 try 775 { 776 Reference< XConnection > xConnection; 777 getConnection( xConnection ); 778 Reference< XDatabaseMetaData > xMeta; 779 if ( xConnection.is() ) 780 xMeta = xConnection->getMetaData(); 781 if ( xMeta.is() ) 782 { 783 m_sIdentifierQuoteString = xMeta->getIdentifierQuoteString(); 784 m_sSpecialCharacters = xMeta->getExtraNameCharacters(); 785 } 786 } 787 catch( const Exception& ) 788 { 789 OSL_ENSURE( sal_False, "ParameterManager::cacheConnectionInfo: caught an exception!" ); 790 } 791 } 792 793 //-------------------------------------------------------------------- 794 bool ParameterManager::getColumns( Reference< XNameAccess >& /* [out] */ _rxColumns, bool _bFromComposer ) SAL_THROW(( Exception )) 795 { 796 _rxColumns.clear(); 797 798 Reference< XColumnsSupplier > xColumnSupp; 799 if ( _bFromComposer ) 800 xColumnSupp = xColumnSupp.query( m_xComposer ); 801 else 802 xColumnSupp.set( m_xComponent.get(),UNO_QUERY); 803 if ( xColumnSupp.is() ) 804 _rxColumns = xColumnSupp->getColumns(); 805 OSL_ENSURE( _rxColumns.is(), "ParameterManager::getColumns: could not retrieve the columns for the detail !" ); 806 807 return _rxColumns.is(); 808 } 809 810 //-------------------------------------------------------------------- 811 bool ParameterManager::getParentColumns( Reference< XNameAccess >& /* [out] */ _out_rxParentColumns, bool _bFromComposer ) 812 { 813 OSL_PRECOND( isAlive(), "ParameterManager::getParentColumns: not initialized, or already disposed!" ); 814 815 _out_rxParentColumns.clear(); 816 try 817 { 818 // get the parent of the component we're working for 819 Reference< XChild > xAsChild( m_xComponent.get(), UNO_QUERY_THROW ); 820 Reference< XPropertySet > xParent( xAsChild->getParent(), UNO_QUERY ); 821 if ( !xParent.is() ) 822 return false; 823 824 // the columns supplier: either from a composer, or directly from the 825 Reference< XColumnsSupplier > xParentColSupp; 826 if ( _bFromComposer ) 827 { 828 // re-create the parent composer all the time. Else, we'd have to bother with 829 // being a listener at its properties, its loaded state, and event the parent-relationship. 830 m_xParentComposer.reset( 831 getCurrentSettingsComposer( xParent, m_xORB ), 832 SharedQueryComposer::TakeOwnership 833 ); 834 xParentColSupp = xParentColSupp.query( m_xParentComposer ); 835 } 836 else 837 xParentColSupp = xParentColSupp.query( xParent ); 838 839 // get the columns of the parent 840 if ( xParentColSupp.is() ) 841 _out_rxParentColumns = xParentColSupp->getColumns(); 842 } 843 catch( const Exception& ) 844 { 845 OSL_ENSURE( sal_False, "ParameterManager::getParentColumns: caught an exception!" ); 846 } 847 return _out_rxParentColumns.is(); 848 } 849 850 //-------------------------------------------------------------------- 851 void ParameterManager::addParameterListener( const Reference< XDatabaseParameterListener >& _rxListener ) 852 { 853 if ( _rxListener.is() ) 854 m_aParameterListeners.addInterface( _rxListener ); 855 } 856 857 //-------------------------------------------------------------------- 858 void ParameterManager::removeParameterListener( const Reference< XDatabaseParameterListener >& _rxListener ) 859 { 860 m_aParameterListeners.removeInterface( _rxListener ); 861 } 862 863 //-------------------------------------------------------------------- 864 void ParameterManager::resetParameterValues( ) SAL_THROW(()) 865 { 866 OSL_PRECOND( isAlive(), "ParameterManager::resetParameterValues: not initialized, or already disposed!" ); 867 if ( !isAlive() ) 868 return; 869 870 if ( !m_nInnerCount ) 871 // no parameters at all 872 return; 873 874 try 875 { 876 Reference< XNameAccess > xColumns; 877 if ( !getColumns( xColumns, false ) ) 878 // already asserted in getColumns 879 return; 880 881 Reference< XNameAccess > xParentColumns; 882 if ( !getParentColumns( xParentColumns, false ) ) 883 return; 884 885 // loop through all links pairs 886 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray(); 887 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray(); 888 889 Reference< XPropertySet > xMasterField; 890 Reference< XPropertySet > xDetailField; 891 892 // now really .... 893 const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength(); 894 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields ) 895 { 896 if ( !xParentColumns->hasByName( *pMasterFields ) ) 897 { 898 // if this name is unknown in the parent columns, then we don't have a source 899 // for copying the value to the detail columns 900 OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: this should have been stripped long before!" ); 901 continue; 902 } 903 904 // for all inner parameters which are bound to the name as specified by the 905 // slave element of the link, propagate the value from the master column to this 906 // parameter column 907 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields ); 908 if ( ( aParamInfo == m_aParameterInformation.end() ) 909 || ( aParamInfo->second.aInnerIndexes.empty() ) 910 ) 911 { 912 OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: nothing known about this detail field!" ); 913 continue; 914 } 915 916 xParentColumns->getByName( *pMasterFields ) >>= xMasterField; 917 if ( !xMasterField.is() ) 918 continue; 919 920 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin(); 921 aPosition != aParamInfo->second.aInnerIndexes.end(); 922 ++aPosition 923 ) 924 { 925 Reference< XPropertySet > xInnerParameter; 926 m_xInnerParamColumns->getByIndex( *aPosition ) >>= xInnerParameter; 927 if ( !xInnerParameter.is() ) 928 continue; 929 930 ::rtl::OUString sParamColumnRealName; 931 xInnerParameter->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME) ) >>= sParamColumnRealName; 932 if ( xColumns->hasByName( sParamColumnRealName ) ) 933 { // our own columns have a column which's name equals the real name of the param column 934 // -> transfer the value property 935 xColumns->getByName( sParamColumnRealName ) >>= xDetailField; 936 if ( xDetailField.is() ) 937 xDetailField->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ) ); 938 } 939 } 940 } 941 } 942 catch( const Exception& ) 943 { 944 OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: caught an exception!" ); 945 } 946 947 } 948 949 //-------------------------------------------------------------------- 950 void ParameterManager::externalParameterVisited( sal_Int32 _nIndex ) 951 { 952 if ( m_aParametersVisited.size() < (size_t)_nIndex ) 953 { 954 m_aParametersVisited.reserve( _nIndex ); 955 for ( sal_Int32 i = m_aParametersVisited.size(); i < _nIndex; ++i ) 956 m_aParametersVisited.push_back( false ); 957 } 958 m_aParametersVisited[ _nIndex - 1 ] = true; 959 } 960 961 #define VISIT_PARAMETER( method ) \ 962 ::osl::MutexGuard aGuard( m_rMutex ); \ 963 OSL_ENSURE( m_xInnerParamUpdate.is(), "ParameterManager::XParameters::setXXX: no XParameters access to the RowSet!" ); \ 964 if ( !m_xInnerParamUpdate.is() ) \ 965 return; \ 966 m_xInnerParamUpdate->method; \ 967 externalParameterVisited( _nIndex ) \ 968 969 //-------------------------------------------------------------------- 970 void ParameterManager::setNull( sal_Int32 _nIndex, sal_Int32 sqlType ) 971 { 972 VISIT_PARAMETER( setNull( _nIndex, sqlType ) ); 973 } 974 975 //-------------------------------------------------------------------- 976 void ParameterManager::setObjectNull( sal_Int32 _nIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) 977 { 978 VISIT_PARAMETER( setObjectNull( _nIndex, sqlType, typeName ) ); 979 } 980 981 //-------------------------------------------------------------------- 982 void ParameterManager::setBoolean( sal_Int32 _nIndex, sal_Bool x ) 983 { 984 VISIT_PARAMETER( setBoolean( _nIndex, x ) ); 985 } 986 987 //-------------------------------------------------------------------- 988 void ParameterManager::setByte( sal_Int32 _nIndex, sal_Int8 x ) 989 { 990 VISIT_PARAMETER( setByte( _nIndex, x ) ); 991 } 992 993 //-------------------------------------------------------------------- 994 void ParameterManager::setShort( sal_Int32 _nIndex, sal_Int16 x ) 995 { 996 VISIT_PARAMETER( setShort( _nIndex, x ) ); 997 } 998 999 //-------------------------------------------------------------------- 1000 void ParameterManager::setInt( sal_Int32 _nIndex, sal_Int32 x ) 1001 { 1002 VISIT_PARAMETER( setInt( _nIndex, x ) ); 1003 } 1004 1005 //-------------------------------------------------------------------- 1006 void ParameterManager::setLong( sal_Int32 _nIndex, sal_Int64 x ) 1007 { 1008 VISIT_PARAMETER( setLong( _nIndex, x ) ); 1009 } 1010 1011 //-------------------------------------------------------------------- 1012 void ParameterManager::setFloat( sal_Int32 _nIndex, float x ) 1013 { 1014 VISIT_PARAMETER( setFloat( _nIndex, x ) ); 1015 } 1016 1017 //-------------------------------------------------------------------- 1018 void ParameterManager::setDouble( sal_Int32 _nIndex, double x ) 1019 { 1020 VISIT_PARAMETER( setDouble( _nIndex, x ) ); 1021 } 1022 1023 //-------------------------------------------------------------------- 1024 void ParameterManager::setString( sal_Int32 _nIndex, const ::rtl::OUString& x ) 1025 { 1026 VISIT_PARAMETER( setString( _nIndex, x ) ); 1027 } 1028 1029 //-------------------------------------------------------------------- 1030 void ParameterManager::setBytes( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) 1031 { 1032 VISIT_PARAMETER( setBytes( _nIndex, x ) ); 1033 } 1034 1035 //-------------------------------------------------------------------- 1036 void ParameterManager::setDate( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x ) 1037 { 1038 VISIT_PARAMETER( setDate( _nIndex, x ) ); 1039 } 1040 1041 //-------------------------------------------------------------------- 1042 void ParameterManager::setTime( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x ) 1043 { 1044 VISIT_PARAMETER( setTime( _nIndex, x ) ); 1045 } 1046 1047 //-------------------------------------------------------------------- 1048 void ParameterManager::setTimestamp( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x ) 1049 { 1050 VISIT_PARAMETER( setTimestamp( _nIndex, x ) ); 1051 } 1052 1053 //-------------------------------------------------------------------- 1054 void ParameterManager::setBinaryStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length ) 1055 { 1056 VISIT_PARAMETER( setBinaryStream( _nIndex, x, length ) ); 1057 } 1058 1059 //-------------------------------------------------------------------- 1060 void ParameterManager::setCharacterStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length ) 1061 { 1062 VISIT_PARAMETER( setCharacterStream( _nIndex, x, length ) ); 1063 } 1064 1065 //-------------------------------------------------------------------- 1066 void ParameterManager::setObject( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x ) 1067 { 1068 VISIT_PARAMETER( setObject( _nIndex, x ) ); 1069 } 1070 1071 //-------------------------------------------------------------------- 1072 void ParameterManager::setObjectWithInfo( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) 1073 { 1074 VISIT_PARAMETER( setObjectWithInfo( _nIndex, x, targetSqlType, scale ) ); 1075 } 1076 1077 //-------------------------------------------------------------------- 1078 void ParameterManager::setRef( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x ) 1079 { 1080 VISIT_PARAMETER( setRef( _nIndex, x ) ); 1081 } 1082 1083 //-------------------------------------------------------------------- 1084 void ParameterManager::setBlob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x ) 1085 { 1086 VISIT_PARAMETER( setBlob( _nIndex, x ) ); 1087 } 1088 1089 //-------------------------------------------------------------------- 1090 void ParameterManager::setClob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x ) 1091 { 1092 VISIT_PARAMETER( setClob( _nIndex, x ) ); 1093 } 1094 1095 //-------------------------------------------------------------------- 1096 void ParameterManager::setArray( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x ) 1097 { 1098 VISIT_PARAMETER( setArray( _nIndex, x ) ); 1099 } 1100 1101 //-------------------------------------------------------------------- 1102 void ParameterManager::clearParameters( ) 1103 { 1104 if ( m_xInnerParamUpdate.is() ) 1105 m_xInnerParamUpdate->clearParameters( ); 1106 } 1107 1108 //==================================================================== 1109 //= OParameterContinuation 1110 //==================================================================== 1111 //-------------------------------------------------------------------- 1112 void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw( RuntimeException ) 1113 { 1114 m_aValues = _rValues; 1115 } 1116 1117 //........................................................................ 1118 } // namespace frm 1119 //........................................................................ 1120 1121