Bump for 3.6-28
[LibreOffice.git] / connectivity / source / commontools / parameters.cxx
bloba448bf13ae870bc507c90ebaddbbb75a6b81f31e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "connectivity/parameters.hxx"
31 /** === begin UNO includes === **/
32 #include <com/sun/star/form/DatabaseParameterEvent.hpp>
33 #include <com/sun/star/sdbc/XParameters.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
36 #include <com/sun/star/container/XEnumerationAccess.hpp>
37 #include <com/sun/star/sdb/XParametersSupplier.hpp>
38 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
39 #include <com/sun/star/sdb/ParametersRequest.hpp>
40 /** === end UNO includes === **/
42 #include <connectivity/dbtools.hxx>
43 #include "connectivity/filtermanager.hxx"
44 #include "TConnection.hxx"
46 #include <tools/debug.hxx>
47 #include <tools/diagnose_ex.h>
49 #include <comphelper/uno3.hxx>
50 #include <comphelper/proparrhlp.hxx>
51 #include <comphelper/broadcasthelper.hxx>
52 #include "connectivity/ParameterCont.hxx"
53 #include <rtl/ustrbuf.hxx>
55 //........................................................................
56 namespace dbtools
58 //........................................................................
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::sdb;
62 using namespace ::com::sun::star::sdbc;
63 using namespace ::com::sun::star::sdbcx;
64 using namespace ::com::sun::star::lang;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::task;
67 using namespace ::com::sun::star::form;
68 using namespace ::com::sun::star::container;
70 using namespace ::comphelper;
71 using namespace ::connectivity;
73 //====================================================================
74 //= ParameterManager
75 //====================================================================
76 //--------------------------------------------------------------------
77 ParameterManager::ParameterManager( ::osl::Mutex& _rMutex, const Reference< XMultiServiceFactory >& _rxORB )
78 :m_rMutex ( _rMutex )
79 ,m_aParameterListeners( _rMutex )
80 ,m_xORB ( _rxORB )
81 ,m_pOuterParameters ( NULL )
82 ,m_nInnerCount ( 0 )
83 ,m_bUpToDate ( false )
85 OSL_ENSURE( m_xORB.is(), "ParameterManager::ParameterManager: no service factory!" );
88 //--------------------------------------------------------------------
89 void ParameterManager::initialize( const Reference< XPropertySet >& _rxComponent, const Reference< XAggregation >& _rxComponentAggregate )
91 OSL_ENSURE( !m_xComponent.get().is(), "ParameterManager::initialize: already initialized!" );
93 m_xComponent = _rxComponent;
94 m_xAggregatedRowSet = _rxComponentAggregate;
95 if ( m_xAggregatedRowSet.is() )
96 m_xAggregatedRowSet->queryAggregation( ::getCppuType( &m_xInnerParamUpdate ) ) >>= m_xInnerParamUpdate;
97 OSL_ENSURE( m_xComponent.get().is() && m_xInnerParamUpdate.is(), "ParameterManager::initialize: invalid arguments!" );
98 if ( !m_xComponent.get().is() || !m_xInnerParamUpdate.is() )
99 return;
102 //--------------------------------------------------------------------
103 void ParameterManager::dispose( )
105 clearAllParameterInformation();
107 m_xComposer.clear();
108 m_xParentComposer.clear();
109 //m_xComponent.clear();
110 m_xInnerParamUpdate.clear();
111 m_xAggregatedRowSet.clear();
114 //--------------------------------------------------------------------
115 void ParameterManager::clearAllParameterInformation()
117 m_xInnerParamColumns.clear();
118 if ( m_pOuterParameters.is() )
119 m_pOuterParameters->dispose();
120 m_pOuterParameters = NULL;
121 m_nInnerCount = 0;
122 ParameterInformation aEmptyInfo;
123 m_aParameterInformation.swap( aEmptyInfo );
124 m_aMasterFields.realloc( 0 );
125 m_aDetailFields.realloc( 0 );
126 m_sIdentifierQuoteString = ::rtl::OUString();
127 ::std::vector< bool > aEmptyArray;
128 m_aParametersVisited.swap( aEmptyArray );
129 m_bUpToDate = false;
132 //--------------------------------------------------------------------
133 void ParameterManager::disposing( const EventObject& /*_rDisposingEvent*/ )
137 //--------------------------------------------------------------------
138 void ParameterManager::setAllParametersNull() SAL_THROW( ( SQLException, RuntimeException ) )
140 OSL_PRECOND( isAlive(), "ParameterManager::setAllParametersNull: not initialized, or already disposed!" );
141 if ( !isAlive() )
142 return;
144 for ( sal_Int32 i = 1; i <= m_nInnerCount; ++i )
145 m_xInnerParamUpdate->setNull( i, DataType::VARCHAR );
148 //--------------------------------------------------------------------
149 bool ParameterManager::initializeComposerByComponent( const Reference< XPropertySet >& _rxComponent )
151 OSL_PRECOND( _rxComponent.is(), "ParameterManager::initializeComposerByComponent: invalid !" );
153 m_xComposer.clear();
154 m_xInnerParamColumns.clear();
155 m_nInnerCount = 0;
157 // create and fill a composer
160 // get a query composer for the 's settings
161 m_xComposer.reset( getCurrentSettingsComposer( _rxComponent, m_xORB ), SharedQueryComposer::TakeOwnership );
163 // see if the composer found parameters
164 Reference< XParametersSupplier > xParamSupp( m_xComposer, UNO_QUERY );
165 if ( xParamSupp.is() )
166 m_xInnerParamColumns = xParamSupp->getParameters();
168 if ( m_xInnerParamColumns.is() )
169 m_nInnerCount = m_xInnerParamColumns->getCount();
171 catch( const SQLException& )
175 return m_xInnerParamColumns.is();
178 //--------------------------------------------------------------------
179 void ParameterManager::collectInnerParameters( bool _bSecondRun )
181 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::collectInnerParameters: missing some internal data!" );
182 if ( !m_xInnerParamColumns.is() )
183 return;
185 // strip previous index informations
186 if ( _bSecondRun )
188 for ( ParameterInformation::iterator aParamInfo = m_aParameterInformation.begin();
189 aParamInfo != m_aParameterInformation.end();
190 ++aParamInfo
193 aParamInfo->second.aInnerIndexes.clear();
197 // we need to map the parameter names (which is all we get from the 's
198 // MasterFields property) to indicies, which are needed by the XParameters
199 // interface of the row set)
200 Reference<XPropertySet> xParam;
201 for ( sal_Int32 i = 0; i < m_nInnerCount; ++i )
205 xParam.clear();
206 m_xInnerParamColumns->getByIndex( i ) >>= xParam;
208 ::rtl::OUString sName;
209 xParam->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName;
211 // only append additonal parameters when they are not already in the list
212 ParameterInformation::iterator aExistentPos = m_aParameterInformation.find( sName );
213 OSL_ENSURE( !_bSecondRun || ( aExistentPos != m_aParameterInformation.end() ),
214 "ParameterManager::collectInnerParameters: the parameter information should already exist in the second run!" );
216 if ( aExistentPos == m_aParameterInformation.end() )
218 aExistentPos = m_aParameterInformation.insert( ParameterInformation::value_type(
219 sName, xParam ) ).first;
221 else
222 aExistentPos->second.xComposerColumn = xParam;
224 aExistentPos->second.aInnerIndexes.push_back( i );
226 catch( const Exception& )
228 OSL_FAIL( "ParameterManager::collectInnerParameters: caught an exception!" );
233 //--------------------------------------------------------------------
234 ::rtl::OUString ParameterManager::createFilterConditionFromColumnLink(
235 const ::rtl::OUString& _rMasterColumn, const ::rtl::OUString& _rDetailLink, ::rtl::OUString& _rNewParamName )
237 ::rtl::OUString sFilter;
239 // format is:
240 // <detail_column> = :<new_param_name>
241 sFilter = quoteName( m_sIdentifierQuoteString, _rDetailLink );
242 sFilter += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( " = :" ));
244 // generate a parameter name which is not already used
245 _rNewParamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "link_from_" ) );
246 _rNewParamName += convertName2SQLName( _rMasterColumn, m_sSpecialCharacters );
247 while ( m_aParameterInformation.find( _rNewParamName ) != m_aParameterInformation.end() )
249 _rNewParamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_" ) );
252 return sFilter += _rNewParamName;
255 //--------------------------------------------------------------------
256 void ParameterManager::classifyLinks( const Reference< XNameAccess >& _rxParentColumns,
257 const Reference< XNameAccess >& _rxColumns, ::std::vector< ::rtl::OUString >& _out_rAdditionalFilterComponents ) SAL_THROW(( Exception ))
259 OSL_PRECOND( m_aMasterFields.getLength() == m_aDetailFields.getLength(),
260 "ParameterManager::classifyLinks: master and detail fields should have the same length!" );
261 OSL_ENSURE( _rxColumns.is(), "ParameterManager::classifyLinks: invalid columns!" );
263 if ( !_rxColumns.is() )
264 return;
266 // we may need to strip any links which are invalid, so here go the containers
267 // for temporarirly holding the new pairs
268 ::std::vector< ::rtl::OUString > aStrippedMasterFields;
269 ::std::vector< ::rtl::OUString > aStrippedDetailFields;
271 bool bNeedExchangeLinks = false;
273 // classify the links
274 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray();
275 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray();
276 const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength();
277 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields )
279 if ( pMasterFields->isEmpty() || pDetailFields->isEmpty() )
280 continue;
282 // if not even the master part of the relationship exists in the parent , the
283 // link is invalid as a whole
284 // #i63674# / 2006-03-28 / frank.schoenheit@sun.com
285 if ( !_rxParentColumns->hasByName( *pMasterFields ) )
287 bNeedExchangeLinks = true;
288 continue;
291 bool bValidLink = true;
293 // is there an inner parameter with this name? That is, a parameter which is already part of
294 // the very original statement (not the one we create ourselve, with the additional parameters)
295 ParameterInformation::iterator aPos = m_aParameterInformation.find( *pDetailFields );
296 if ( aPos != m_aParameterInformation.end() )
297 { // there is an inner parameter with this name
298 aPos->second.eType = eLinkedByParamName;
299 aStrippedDetailFields.push_back( *pDetailFields );
301 else
303 // does the detail name denote a column?
304 if ( _rxColumns->hasByName( *pDetailFields ) )
306 ::rtl::OUString sNewParamName;
307 const ::rtl::OUString sFilterCondition = createFilterConditionFromColumnLink( *pMasterFields, *pDetailFields, sNewParamName );
308 OSL_PRECOND( !sNewParamName.isEmpty(), "ParameterManager::classifyLinks: createFilterConditionFromColumnLink returned nonsense!" );
310 // remember meta information about this new parameter
311 ::std::pair< ParameterInformation::iterator, bool > aInsertionPos =
312 m_aParameterInformation.insert(
313 ParameterInformation::value_type( sNewParamName, ParameterMetaData( NULL ) )
315 OSL_ENSURE( aInsertionPos.second, "ParameterManager::classifyLinks: there already was a parameter with this name!" );
316 aInsertionPos.first->second.eType = eLinkedByColumnName;
318 // remember the filter component
319 _out_rAdditionalFilterComponents.push_back( sFilterCondition );
321 // remember the new "detail field" for this link
322 aStrippedDetailFields.push_back( sNewParamName );
323 bNeedExchangeLinks = true;
325 else
327 // the detail field neither denotes a column name, nor a parameter name
328 bValidLink = false;
329 bNeedExchangeLinks = true;
333 if ( bValidLink )
334 aStrippedMasterFields.push_back( *pMasterFields );
336 OSL_POSTCOND( aStrippedMasterFields.size() == aStrippedDetailFields.size(),
337 "ParameterManager::classifyLinks: inconsistency in new link pairs!" );
339 if ( bNeedExchangeLinks )
341 ::rtl::OUString *pFields = aStrippedMasterFields.empty() ? 0 : &aStrippedMasterFields[0];
342 m_aMasterFields = Sequence< ::rtl::OUString >( pFields, aStrippedMasterFields.size() );
343 pFields = aStrippedDetailFields.empty() ? 0 : &aStrippedDetailFields[0];
344 m_aDetailFields = Sequence< ::rtl::OUString >( pFields, aStrippedDetailFields.size() );
348 //--------------------------------------------------------------------
349 void ParameterManager::analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails )
351 OSL_PRECOND( isAlive(), "ParameterManager::analyzeFieldLinks: not initialized, or already disposed!" );
352 if ( !isAlive() )
353 return;
355 _rColumnsInLinkDetails = false;
358 // the links as determined by the properties
359 Reference< XPropertySet > xProp = m_xComponent;
360 OSL_ENSURE(xProp.is(),"Some already released my component!");
361 if ( xProp.is() )
363 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MASTERFIELDS) ) >>= m_aMasterFields;
364 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DETAILFIELDS) ) >>= m_aDetailFields;
368 // normalize to equal length
369 sal_Int32 nMasterLength = m_aMasterFields.getLength();
370 sal_Int32 nDetailLength = m_aDetailFields.getLength();
372 if ( nMasterLength > nDetailLength )
373 m_aMasterFields.realloc( nDetailLength );
374 else if ( nDetailLength > nMasterLength )
375 m_aDetailFields.realloc( nMasterLength );
378 Reference< XNameAccess > xColumns;
379 if ( !getColumns( xColumns, true ) )
380 // already asserted in getColumns
381 return;
383 Reference< XNameAccess > xParentColumns;
384 if ( !getParentColumns( xParentColumns, true ) )
385 return;
387 // classify the links - depending on what the detail fields in each link pair denotes
388 ::std::vector< ::rtl::OUString > aAdditionalFilterComponents;
389 classifyLinks( xParentColumns, xColumns, aAdditionalFilterComponents );
391 // did we find links where the detail field refers to a detail column (instead of a parameter name)?
392 if ( !aAdditionalFilterComponents.empty() )
394 const static ::rtl::OUString s_sAnd( RTL_CONSTASCII_USTRINGPARAM( " AND " ) );
395 // build a conjunction of all the filter components
396 ::rtl::OUStringBuffer sAdditionalFilter;
397 for ( ::std::vector< ::rtl::OUString >::const_iterator aComponent = aAdditionalFilterComponents.begin();
398 aComponent != aAdditionalFilterComponents.end();
399 ++aComponent
402 if ( sAdditionalFilter.getLength() )
403 sAdditionalFilter.append(s_sAnd);
405 sAdditionalFilter.appendAscii("( ",((sal_Int32)(sizeof("( ")-1)));
406 sAdditionalFilter.append(*aComponent);
407 sAdditionalFilter.appendAscii(" )",((sal_Int32)(sizeof(" )")-1)));
410 // now set this filter at the 's filter manager
411 _rFilterManager.setFilterComponent( FilterManager::fcLinkFilter, sAdditionalFilter.makeStringAndClear() );
413 _rColumnsInLinkDetails = true;
416 catch( const Exception& )
418 OSL_FAIL( "ParameterManager::analyzeFieldLinks: caught an exception!" );
422 //--------------------------------------------------------------------
423 void ParameterManager::createOuterParameters()
425 OSL_PRECOND( !m_pOuterParameters.is(), "ParameterManager::createOuterParameters: outer parameters not initialized!" );
426 OSL_PRECOND( m_xInnerParamUpdate.is(), "ParameterManager::createOuterParameters: no write access to the inner parameters!" );
427 if ( !m_xInnerParamUpdate.is() )
428 return;
430 m_pOuterParameters = new param::ParameterWrapperContainer;
432 #if OSL_DEBUG_LEVEL > 0
433 sal_Int32 nSmallestIndexLinkedByColumnName = -1;
434 sal_Int32 nLargestIndexNotLinkedByColumnName = -1;
435 #endif
436 ::rtl::OUString sName;
437 for ( ParameterInformation::iterator aParam = m_aParameterInformation.begin();
438 aParam != m_aParameterInformation.end();
439 ++aParam
442 #if OSL_DEBUG_LEVEL > 0
443 if ( aParam->second.aInnerIndexes.size() )
445 if ( aParam->second.eType == eLinkedByColumnName )
447 if ( nSmallestIndexLinkedByColumnName == -1 )
448 nSmallestIndexLinkedByColumnName = aParam->second.aInnerIndexes[ 0 ];
450 else
452 nLargestIndexNotLinkedByColumnName = aParam->second.aInnerIndexes[ aParam->second.aInnerIndexes.size() - 1 ];
455 #endif
456 if ( aParam->second.eType != eFilledExternally )
457 continue;
459 // check which of the parameters have already been visited (e.g. filled via XParameters)
460 size_t nAlreadyVisited = 0;
461 for ( ::std::vector< sal_Int32 >::iterator aIndex = aParam->second.aInnerIndexes.begin();
462 aIndex != aParam->second.aInnerIndexes.end();
463 ++aIndex
466 if ( ( m_aParametersVisited.size() > (size_t)*aIndex ) && m_aParametersVisited[ *aIndex ] )
467 { // exclude this index
468 *aIndex = -1;
469 ++nAlreadyVisited;
472 if ( nAlreadyVisited == aParam->second.aInnerIndexes.size() )
473 continue;
475 // need a wrapper for this .... the "inner parameters" as supplied by a result set don't have a "Value"
476 // property, but the parameter listeners expect such a property. So we need an object "aggregating"
477 // xParam and supplying an additional property ("Value")
478 // (it's no real aggregation of course ...)
479 m_pOuterParameters->push_back( new param::ParameterWrapper( aParam->second.xComposerColumn, m_xInnerParamUpdate, aParam->second.aInnerIndexes ) );
482 #if OSL_DEBUG_LEVEL > 0
483 OSL_ENSURE( ( nSmallestIndexLinkedByColumnName == -1 ) || ( nLargestIndexNotLinkedByColumnName == -1 ) ||
484 ( nSmallestIndexLinkedByColumnName > nLargestIndexNotLinkedByColumnName ),
485 "ParameterManager::createOuterParameters: inconsistency!" );
487 // for the master-detail links, where the detail field denoted a column name, we created an addtional ("artificial")
488 // filter, and *appended* it to all other (potentially) existing filters of the row set. This means that the indexes
489 // for the parameters resulting from the artifical filter should be larger than any other parameter index, and this
490 // is what the assertion checks.
491 // If the assertion fails, then we would need another handling for the "parameters visited" flags, since they're based
492 // on parameter indexes *without* the artificial filter (because this filter is not visible from the outside).
493 #endif
496 //--------------------------------------------------------------------
497 void ParameterManager::updateParameterInfo( FilterManager& _rFilterManager )
499 OSL_PRECOND( isAlive(), "ParameterManager::updateParameterInfo: not initialized, or already disposed!" );
500 if ( !isAlive() )
501 return;
503 clearAllParameterInformation();
504 cacheConnectionInfo();
506 // check whether the is based on a statement/query which requires parameters
507 Reference< XPropertySet > xProp = m_xComponent;
508 OSL_ENSURE(xProp.is(),"Some already released my component!");
509 if ( xProp.is() )
511 if ( !initializeComposerByComponent( xProp ) )
512 { // okay, nothing to do
513 m_bUpToDate = true;
514 return;
515 } // if ( !initializeComposerByComponent( m_xComponent ) )
517 OSL_POSTCOND( m_xInnerParamColumns.is(), "ParameterManager::updateParameterInfo: initializeComposerByComponent did nonsense (1)!" );
519 // collect all parameters which are defined by the "inner parameters"
520 collectInnerParameters( false );
522 // analyze the master-detail relationships
523 bool bColumnsInLinkDetails = false;
524 analyzeFieldLinks( _rFilterManager, bColumnsInLinkDetails );
526 if ( bColumnsInLinkDetails )
528 // okay, in this case, analyzeFieldLinks modified the "real" filter at the RowSet, to contain
529 // an additional restriction (which we created ourself)
530 // So we need to update all information about our inner parameter columns
531 Reference< XPropertySet > xDirectRowSetProps;
532 m_xAggregatedRowSet->queryAggregation( ::getCppuType( &xDirectRowSetProps ) ) >>= xDirectRowSetProps;
533 OSL_VERIFY( initializeComposerByComponent( xDirectRowSetProps ) );
534 collectInnerParameters( true );
537 if ( !m_nInnerCount )
538 { // no parameters at all
539 m_bUpToDate = true;
540 return;
543 // for what now remains as outer parameters, create the wrappers for the single
544 // parameter columns
545 createOuterParameters();
547 m_bUpToDate = true;
550 //--------------------------------------------------------------------
551 void ParameterManager::fillLinkedParameters( const Reference< XNameAccess >& _rxParentColumns )
553 OSL_PRECOND( isAlive(), "ParameterManager::fillLinkedParameters: not initialized, or already disposed!" );
554 if ( !isAlive() )
555 return;
556 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::fillLinkedParameters: no inner parameters found!" );
557 OSL_ENSURE ( _rxParentColumns.is(), "ParameterManager::fillLinkedParameters: invalid parent columns!" );
561 // the master and detail field( name)s of the
562 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray();
563 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray();
565 sal_Int32 nMasterLen = m_aMasterFields.getLength();
566 Any aParamType, aScale, aValue;
568 // loop through all master fields. For each of them, get the respective column from the
569 // parent , and forward it's current value as paramter value to the (inner) row set
570 for ( sal_Int32 i = 0; i < nMasterLen; ++i, ++pMasterFields, ++pDetailFields )
572 // does the name denote a valid column in the parent?
573 if ( !_rxParentColumns->hasByName( *pMasterFields ) )
575 OSL_FAIL( "ParameterManager::fillLinkedParameters: invalid master names should have been stripped long before!" );
576 continue;
579 // do we, for this name, know where to place the values?
580 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields );
581 if ( ( aParamInfo == m_aParameterInformation.end() )
582 || ( aParamInfo->second.aInnerIndexes.empty() )
585 OSL_FAIL( "ParameterManager::fillLinkedParameters: nothing known about this detail field!" );
586 continue;
589 // the concrete master field
590 Reference< XPropertySet > xMasterField(_rxParentColumns->getByName( *pMasterFields ),UNO_QUERY);
592 // the positions where we have to fill in values for the current parameter name
593 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin();
594 aPosition != aParamInfo->second.aInnerIndexes.end();
595 ++aPosition
598 // the concrete detail field
599 Reference< XPropertySet > xDetailField(m_xInnerParamColumns->getByIndex( *aPosition ),UNO_QUERY);
600 OSL_ENSURE( xDetailField.is(), "ParameterManager::fillLinkedParameters: invalid detail field!" );
601 if ( !xDetailField.is() )
602 continue;
604 // type and scale of the parameter field
605 sal_Int32 nParamType = DataType::VARCHAR;
606 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nParamType );
608 sal_Int32 nScale = 0;
609 if ( xDetailField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) )
610 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) >>= nScale );
612 // transfer the param value
615 m_xInnerParamUpdate->setObjectWithInfo(
616 *aPosition + 1, // parameters are based at 1
617 xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ),
618 nParamType,
619 nScale
622 catch( const Exception& )
624 OSL_FAIL( ( ::rtl::OString( "ParameterManager::fillLinkedParameters: master-detail parameter number " )
625 += ::rtl::OString::valueOf( sal_Int32( *aPosition + 1 ) )
626 += ::rtl::OString( " could not be filled!" ) ).getStr() );
631 catch( const Exception& )
633 DBG_UNHANDLED_EXCEPTION();
637 //--------------------------------------------------------------------
638 bool ParameterManager::completeParameters( const Reference< XInteractionHandler >& _rxCompletionHandler, const Reference< XConnection > _rxConnection )
640 OSL_PRECOND( isAlive(), "ParameterManager::completeParameters: not initialized, or already disposed!" );
641 OSL_ENSURE ( _rxCompletionHandler.is(), "ParameterManager::completeParameters: invalid interaction handler!" );
643 // two continuations (Ok and Cancel)
644 OInteractionAbort* pAbort = new OInteractionAbort;
645 OParameterContinuation* pParams = new OParameterContinuation;
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 );
654 // some knittings
655 pRequest->addContinuation( pAbort );
656 pRequest->addContinuation( pParams );
658 // execute the request
661 _rxCompletionHandler->handle( xRequest );
663 catch( const Exception& )
665 OSL_FAIL( "ParameterManager::completeParameters: caught an exception while calling the handler!" );
668 if ( !pParams->wasSelected() )
669 // canceled by the user (i.e. (s)he canceled the dialog)
670 return false;
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 )
679 Reference< XPropertySet > xParamColumn(aRequest.Parameters->getByIndex( i ),UNO_QUERY);
680 if ( xParamColumn.is() )
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
693 catch( const Exception& )
695 OSL_FAIL( "ParameterManager::completeParameters: caught an exception while propagating the values!" );
697 return true;
700 //--------------------------------------------------------------------
701 bool ParameterManager::consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies )
703 bool bCanceled = false;
705 sal_Int32 nParamsLeft = m_pOuterParameters->getParameters().size();
706 // TODO: shouldn't we subtract all the parameters which were already visited?
707 if ( nParamsLeft )
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() );
714 _rClearForNotifies.clear();
715 while ( aIter.hasMoreElements() && !bCanceled )
716 bCanceled = !static_cast< XDatabaseParameterListener* >( aIter.next() )->approveParameter( aEvent );
717 _rClearForNotifies.reset();
720 return !bCanceled;
723 //--------------------------------------------------------------------
724 bool ParameterManager::fillParameterValues( const Reference< XInteractionHandler >& _rxCompletionHandler, ::osl::ResettableMutexGuard& _rClearForNotifies )
726 OSL_PRECOND( isAlive(), "ParameterManager::fillParameterValues: not initialized, or already disposed!" );
727 if ( !isAlive() )
728 return true;
730 if ( m_nInnerCount == 0 )
731 // no parameters at all
732 return true;
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 );
739 // let the user (via the interaction handler) fill all remaining parameters
740 Reference< XConnection > xConnection;
741 getConnection( xConnection );
743 if ( _rxCompletionHandler.is() )
744 return completeParameters( _rxCompletionHandler, xConnection );
746 return consultParameterListeners( _rClearForNotifies );
749 //--------------------------------------------------------------------
750 bool ParameterManager::getConnection( Reference< XConnection >& /* [out] */ _rxConnection )
752 OSL_PRECOND( isAlive(), "ParameterManager::getConnection: not initialized, or already disposed!" );
753 if ( !isAlive() )
754 return false;
756 _rxConnection.clear();
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;
764 catch( const Exception& )
766 OSL_FAIL( "ParameterManager::getConnection: could not retrieve the connection of the !" );
768 return _rxConnection.is();
771 //--------------------------------------------------------------------
772 void ParameterManager::cacheConnectionInfo() SAL_THROW(( ))
776 Reference< XConnection > xConnection;
777 getConnection( xConnection );
778 Reference< XDatabaseMetaData > xMeta;
779 if ( xConnection.is() )
780 xMeta = xConnection->getMetaData();
781 if ( xMeta.is() )
783 m_sIdentifierQuoteString = xMeta->getIdentifierQuoteString();
784 m_sSpecialCharacters = xMeta->getExtraNameCharacters();
787 catch( const Exception& )
789 OSL_FAIL( "ParameterManager::cacheConnectionInfo: caught an exception!" );
793 //--------------------------------------------------------------------
794 bool ParameterManager::getColumns( Reference< XNameAccess >& /* [out] */ _rxColumns, bool _bFromComposer ) SAL_THROW(( Exception ))
796 _rxColumns.clear();
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 !" );
807 return _rxColumns.is();
810 //--------------------------------------------------------------------
811 bool ParameterManager::getParentColumns( Reference< XNameAccess >& /* [out] */ _out_rxParentColumns, bool _bFromComposer )
813 OSL_PRECOND( isAlive(), "ParameterManager::getParentColumns: not initialized, or already disposed!" );
815 _out_rxParentColumns.clear();
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;
824 // the columns supplier: either from a composer, or directly from the
825 Reference< XColumnsSupplier > xParentColSupp;
826 if ( _bFromComposer )
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
834 xParentColSupp = xParentColSupp.query( m_xParentComposer );
836 else
837 xParentColSupp = xParentColSupp.query( xParent );
839 // get the columns of the parent
840 if ( xParentColSupp.is() )
841 _out_rxParentColumns = xParentColSupp->getColumns();
843 catch( const Exception& )
845 OSL_FAIL( "ParameterManager::getParentColumns: caught an exception!" );
847 return _out_rxParentColumns.is();
850 //--------------------------------------------------------------------
851 void ParameterManager::addParameterListener( const Reference< XDatabaseParameterListener >& _rxListener )
853 if ( _rxListener.is() )
854 m_aParameterListeners.addInterface( _rxListener );
857 //--------------------------------------------------------------------
858 void ParameterManager::removeParameterListener( const Reference< XDatabaseParameterListener >& _rxListener )
860 m_aParameterListeners.removeInterface( _rxListener );
863 //--------------------------------------------------------------------
864 void ParameterManager::resetParameterValues( ) SAL_THROW(())
866 OSL_PRECOND( isAlive(), "ParameterManager::resetParameterValues: not initialized, or already disposed!" );
867 if ( !isAlive() )
868 return;
870 if ( !m_nInnerCount )
871 // no parameters at all
872 return;
876 Reference< XNameAccess > xColumns;
877 if ( !getColumns( xColumns, false ) )
878 // already asserted in getColumns
879 return;
881 Reference< XNameAccess > xParentColumns;
882 if ( !getParentColumns( xParentColumns, false ) )
883 return;
885 // loop through all links pairs
886 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray();
887 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray();
889 Reference< XPropertySet > xMasterField;
890 Reference< XPropertySet > xDetailField;
892 // now really ....
893 const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength();
894 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields )
896 if ( !xParentColumns->hasByName( *pMasterFields ) )
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_FAIL( "ParameterManager::resetParameterValues: this should have been stripped long before!" );
901 continue;
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() )
912 OSL_FAIL( "ParameterManager::resetParameterValues: nothing known about this detail field!" );
913 continue;
916 xParentColumns->getByName( *pMasterFields ) >>= xMasterField;
917 if ( !xMasterField.is() )
918 continue;
920 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin();
921 aPosition != aParamInfo->second.aInnerIndexes.end();
922 ++aPosition
925 Reference< XPropertySet > xInnerParameter;
926 m_xInnerParamColumns->getByIndex( *aPosition ) >>= xInnerParameter;
927 if ( !xInnerParameter.is() )
928 continue;
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) ) );
942 catch( const Exception& )
944 OSL_FAIL( "ParameterManager::resetParameterValues: caught an exception!" );
949 //--------------------------------------------------------------------
950 void ParameterManager::externalParameterVisited( sal_Int32 _nIndex )
952 if ( m_aParametersVisited.size() < (size_t)_nIndex )
954 m_aParametersVisited.reserve( _nIndex );
955 for ( sal_Int32 i = m_aParametersVisited.size(); i < _nIndex; ++i )
956 m_aParametersVisited.push_back( false );
958 m_aParametersVisited[ _nIndex - 1 ] = true;
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 ) \
969 //--------------------------------------------------------------------
970 void ParameterManager::setNull( sal_Int32 _nIndex, sal_Int32 sqlType )
972 VISIT_PARAMETER( setNull( _nIndex, sqlType ) );
975 //--------------------------------------------------------------------
976 void ParameterManager::setObjectNull( sal_Int32 _nIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName )
978 VISIT_PARAMETER( setObjectNull( _nIndex, sqlType, typeName ) );
981 //--------------------------------------------------------------------
982 void ParameterManager::setBoolean( sal_Int32 _nIndex, sal_Bool x )
984 VISIT_PARAMETER( setBoolean( _nIndex, x ) );
987 //--------------------------------------------------------------------
988 void ParameterManager::setByte( sal_Int32 _nIndex, sal_Int8 x )
990 VISIT_PARAMETER( setByte( _nIndex, x ) );
993 //--------------------------------------------------------------------
994 void ParameterManager::setShort( sal_Int32 _nIndex, sal_Int16 x )
996 VISIT_PARAMETER( setShort( _nIndex, x ) );
999 //--------------------------------------------------------------------
1000 void ParameterManager::setInt( sal_Int32 _nIndex, sal_Int32 x )
1002 VISIT_PARAMETER( setInt( _nIndex, x ) );
1005 //--------------------------------------------------------------------
1006 void ParameterManager::setLong( sal_Int32 _nIndex, sal_Int64 x )
1008 VISIT_PARAMETER( setLong( _nIndex, x ) );
1011 //--------------------------------------------------------------------
1012 void ParameterManager::setFloat( sal_Int32 _nIndex, float x )
1014 VISIT_PARAMETER( setFloat( _nIndex, x ) );
1017 //--------------------------------------------------------------------
1018 void ParameterManager::setDouble( sal_Int32 _nIndex, double x )
1020 VISIT_PARAMETER( setDouble( _nIndex, x ) );
1023 //--------------------------------------------------------------------
1024 void ParameterManager::setString( sal_Int32 _nIndex, const ::rtl::OUString& x )
1026 VISIT_PARAMETER( setString( _nIndex, x ) );
1029 //--------------------------------------------------------------------
1030 void ParameterManager::setBytes( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x )
1032 VISIT_PARAMETER( setBytes( _nIndex, x ) );
1035 //--------------------------------------------------------------------
1036 void ParameterManager::setDate( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x )
1038 VISIT_PARAMETER( setDate( _nIndex, x ) );
1041 //--------------------------------------------------------------------
1042 void ParameterManager::setTime( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x )
1044 VISIT_PARAMETER( setTime( _nIndex, x ) );
1047 //--------------------------------------------------------------------
1048 void ParameterManager::setTimestamp( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x )
1050 VISIT_PARAMETER( setTimestamp( _nIndex, x ) );
1053 //--------------------------------------------------------------------
1054 void ParameterManager::setBinaryStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length )
1056 VISIT_PARAMETER( setBinaryStream( _nIndex, x, length ) );
1059 //--------------------------------------------------------------------
1060 void ParameterManager::setCharacterStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length )
1062 VISIT_PARAMETER( setCharacterStream( _nIndex, x, length ) );
1065 //--------------------------------------------------------------------
1066 void ParameterManager::setObject( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x )
1068 VISIT_PARAMETER( setObject( _nIndex, x ) );
1071 //--------------------------------------------------------------------
1072 void ParameterManager::setObjectWithInfo( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale )
1074 VISIT_PARAMETER( setObjectWithInfo( _nIndex, x, targetSqlType, scale ) );
1077 //--------------------------------------------------------------------
1078 void ParameterManager::setRef( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x )
1080 VISIT_PARAMETER( setRef( _nIndex, x ) );
1083 //--------------------------------------------------------------------
1084 void ParameterManager::setBlob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x )
1086 VISIT_PARAMETER( setBlob( _nIndex, x ) );
1089 //--------------------------------------------------------------------
1090 void ParameterManager::setClob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x )
1092 VISIT_PARAMETER( setClob( _nIndex, x ) );
1095 //--------------------------------------------------------------------
1096 void ParameterManager::setArray( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x )
1098 VISIT_PARAMETER( setArray( _nIndex, x ) );
1101 //--------------------------------------------------------------------
1102 void ParameterManager::clearParameters( )
1104 if ( m_xInnerParamUpdate.is() )
1105 m_xInnerParamUpdate->clearParameters( );
1108 //====================================================================
1109 //= OParameterContinuation
1110 //====================================================================
1111 //--------------------------------------------------------------------
1112 void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw( RuntimeException )
1114 m_aValues = _rValues;
1117 //........................................................................
1118 } // namespace frm
1119 //........................................................................
1121 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */