merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / commontools / parameters.cxx
blob9114f20e12db80e255deeee6391459ac671a1d0b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: parameters.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "connectivity/parameters.hxx"
35 /** === begin UNO includes === **/
36 #include <com/sun/star/form/DatabaseParameterEvent.hpp>
37 #include <com/sun/star/sdbc/XParameters.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
40 #include <com/sun/star/container/XEnumerationAccess.hpp>
41 #include <com/sun/star/sdb/XParametersSupplier.hpp>
42 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
43 #include <com/sun/star/sdb/ParametersRequest.hpp>
44 /** === end UNO includes === **/
46 #include <connectivity/dbtools.hxx>
47 #include "connectivity/filtermanager.hxx"
48 #include "TConnection.hxx"
50 #include <tools/debug.hxx>
51 #include <tools/diagnose_ex.h>
53 #include <comphelper/uno3.hxx>
54 #include <comphelper/proparrhlp.hxx>
55 #include <comphelper/broadcasthelper.hxx>
56 #include "connectivity/ParameterCont.hxx"
57 #include <rtl/ustrbuf.hxx>
59 //........................................................................
60 namespace dbtools
62 //........................................................................
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::sdb;
66 using namespace ::com::sun::star::sdbc;
67 using namespace ::com::sun::star::sdbcx;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::beans;
70 using namespace ::com::sun::star::task;
71 using namespace ::com::sun::star::form;
72 using namespace ::com::sun::star::container;
74 using namespace ::comphelper;
75 using namespace ::connectivity;
77 //====================================================================
78 //= ParameterManager
79 //====================================================================
80 //--------------------------------------------------------------------
81 ParameterManager::ParameterManager( ::osl::Mutex& _rMutex, const Reference< XMultiServiceFactory >& _rxORB )
82 :m_rMutex ( _rMutex )
83 ,m_aParameterListeners( _rMutex )
84 ,m_xORB ( _rxORB )
85 ,m_pOuterParameters ( NULL )
86 ,m_nInnerCount ( 0 )
87 ,m_bUpToDate ( false )
89 OSL_ENSURE( m_xORB.is(), "ParameterManager::ParameterManager: no service factory!" );
92 //--------------------------------------------------------------------
93 void ParameterManager::initialize( const Reference< XPropertySet >& _rxComponent, const Reference< XAggregation >& _rxComponentAggregate )
95 OSL_ENSURE( !m_xComponent.get().is(), "ParameterManager::initialize: already initialized!" );
97 m_xComponent = _rxComponent;
98 m_xAggregatedRowSet = _rxComponentAggregate;
99 if ( m_xAggregatedRowSet.is() )
100 m_xAggregatedRowSet->queryAggregation( ::getCppuType( &m_xInnerParamUpdate ) ) >>= m_xInnerParamUpdate;
101 OSL_ENSURE( m_xComponent.get().is() && m_xInnerParamUpdate.is(), "ParameterManager::initialize: invalid arguments!" );
102 if ( !m_xComponent.get().is() || !m_xInnerParamUpdate.is() )
103 return;
106 //--------------------------------------------------------------------
107 void ParameterManager::dispose( )
109 clearAllParameterInformation();
111 m_xComposer.clear();
112 m_xParentComposer.clear();
113 //m_xComponent.clear();
114 m_xInnerParamUpdate.clear();
115 m_xAggregatedRowSet.clear();
118 //--------------------------------------------------------------------
119 void ParameterManager::clearAllParameterInformation()
121 m_xInnerParamColumns.clear();
122 if ( m_pOuterParameters.is() )
123 m_pOuterParameters->dispose();
124 m_pOuterParameters = NULL;
125 m_nInnerCount = 0;
126 ParameterInformation aEmptyInfo;
127 m_aParameterInformation.swap( aEmptyInfo );
128 m_aMasterFields.realloc( 0 );
129 m_aDetailFields.realloc( 0 );
130 m_sIdentifierQuoteString = ::rtl::OUString();
131 ::std::vector< bool > aEmptyArray;
132 m_aParametersVisited.swap( aEmptyArray );
133 m_bUpToDate = false;
136 //--------------------------------------------------------------------
137 void ParameterManager::disposing( const EventObject& /*_rDisposingEvent*/ )
141 //--------------------------------------------------------------------
142 void ParameterManager::setAllParametersNull() SAL_THROW( ( SQLException, RuntimeException ) )
144 OSL_PRECOND( isAlive(), "ParameterManager::setAllParametersNull: not initialized, or already disposed!" );
145 if ( !isAlive() )
146 return;
148 for ( sal_Int32 i = 1; i <= m_nInnerCount; ++i )
149 m_xInnerParamUpdate->setNull( i, DataType::VARCHAR );
152 //--------------------------------------------------------------------
153 bool ParameterManager::initializeComposerByComponent( const Reference< XPropertySet >& _rxComponent )
155 OSL_PRECOND( _rxComponent.is(), "ParameterManager::initializeComposerByComponent: invalid !" );
157 m_xComposer.clear();
158 m_xInnerParamColumns.clear();
159 m_nInnerCount = 0;
161 // create and fill a composer
164 // get a query composer for the 's settings
165 m_xComposer.reset( getCurrentSettingsComposer( _rxComponent, m_xORB ), SharedQueryComposer::TakeOwnership );
167 // see if the composer found parameters
168 Reference< XParametersSupplier > xParamSupp( m_xComposer, UNO_QUERY );
169 if ( xParamSupp.is() )
170 m_xInnerParamColumns = xParamSupp->getParameters();
172 if ( m_xInnerParamColumns.is() )
173 m_nInnerCount = m_xInnerParamColumns->getCount();
175 catch( const SQLException& )
179 return m_xInnerParamColumns.is();
182 //--------------------------------------------------------------------
183 void ParameterManager::collectInnerParameters( bool _bSecondRun )
185 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::collectInnerParameters: missing some internal data!" );
186 if ( !m_xInnerParamColumns.is() )
187 return;
189 // strip previous index informations
190 if ( _bSecondRun )
192 for ( ParameterInformation::iterator aParamInfo = m_aParameterInformation.begin();
193 aParamInfo != m_aParameterInformation.end();
194 ++aParamInfo
197 aParamInfo->second.aInnerIndexes.clear();
201 // we need to map the parameter names (which is all we get from the 's
202 // MasterFields property) to indicies, which are needed by the XParameters
203 // interface of the row set)
204 Reference<XPropertySet> xParam;
205 for ( sal_Int32 i = 0; i < m_nInnerCount; ++i )
209 xParam.clear();
210 m_xInnerParamColumns->getByIndex( i ) >>= xParam;
212 ::rtl::OUString sName;
213 xParam->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName;
215 // only append additonal paramters when they are not already in the list
216 ParameterInformation::iterator aExistentPos = m_aParameterInformation.find( sName );
217 OSL_ENSURE( !_bSecondRun || ( aExistentPos != m_aParameterInformation.end() ),
218 "ParameterManager::collectInnerParameters: the parameter information should already exist in the second run!" );
220 if ( aExistentPos == m_aParameterInformation.end() )
222 aExistentPos = m_aParameterInformation.insert( ParameterInformation::value_type(
223 sName, xParam ) ).first;
225 else
226 aExistentPos->second.xComposerColumn = xParam;
228 aExistentPos->second.aInnerIndexes.push_back( i );
230 catch( const Exception& )
232 OSL_ENSURE( sal_False, "ParameterManager::collectInnerParameters: caught an exception!" );
237 //--------------------------------------------------------------------
238 ::rtl::OUString ParameterManager::createFilterConditionFromColumnLink(
239 const ::rtl::OUString& _rMasterColumn, const ::rtl::OUString& _rDetailLink, ::rtl::OUString& _rNewParamName )
241 ::rtl::OUString sFilter;
243 // format is:
244 // <detail_column> = :<new_param_name>
245 sFilter = quoteName( m_sIdentifierQuoteString, _rDetailLink );
246 sFilter += ::rtl::OUString::createFromAscii( " = :" );
248 // generate a parameter name which is not already used
249 _rNewParamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "link_from_" ) );
250 _rNewParamName += convertName2SQLName( _rMasterColumn, m_sSpecialCharacters );
251 while ( m_aParameterInformation.find( _rNewParamName ) != m_aParameterInformation.end() )
253 _rNewParamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_" ) );
256 return sFilter += _rNewParamName;
259 //--------------------------------------------------------------------
260 void ParameterManager::classifyLinks( const Reference< XNameAccess >& _rxParentColumns,
261 const Reference< XNameAccess >& _rxColumns, ::std::vector< ::rtl::OUString >& _out_rAdditionalFilterComponents ) SAL_THROW(( Exception ))
263 OSL_PRECOND( m_aMasterFields.getLength() == m_aDetailFields.getLength(),
264 "ParameterManager::classifyLinks: master and detail fields should have the same length!" );
265 OSL_ENSURE( _rxColumns.is(), "ParameterManager::classifyLinks: invalid columns!" );
267 if ( !_rxColumns.is() )
268 return;
270 // we may need to strip any links which are invalid, so here go the containers
271 // for temporarirly holding the new pairs
272 ::std::vector< ::rtl::OUString > aStrippedMasterFields;
273 ::std::vector< ::rtl::OUString > aStrippedDetailFields;
275 bool bNeedExchangeLinks = false;
277 // classify the links
278 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray();
279 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray();
280 const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength();
281 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields )
283 if ( !pMasterFields->getLength() || !pDetailFields->getLength() )
284 continue;
286 // if not even the master part of the relationship exists in the parent , the
287 // link is invalid as a whole
288 // #i63674# / 2006-03-28 / frank.schoenheit@sun.com
289 if ( !_rxParentColumns->hasByName( *pMasterFields ) )
291 bNeedExchangeLinks = true;
292 continue;
295 bool bValidLink = true;
297 // is there an inner parameter with this name? That is, a parameter which is already part of
298 // the very original statement (not the one we create ourselve, with the additional parameters)
299 ParameterInformation::iterator aPos = m_aParameterInformation.find( *pDetailFields );
300 if ( aPos != m_aParameterInformation.end() )
301 { // there is an inner parameter with this name
302 aPos->second.eType = eLinkedByParamName;
303 aStrippedDetailFields.push_back( *pDetailFields );
305 else
307 // does the detail name denote a column?
308 if ( _rxColumns->hasByName( *pDetailFields ) )
310 ::rtl::OUString sNewParamName;
311 const ::rtl::OUString sFilterCondition = createFilterConditionFromColumnLink( *pMasterFields, *pDetailFields, sNewParamName );
312 OSL_PRECOND( sNewParamName.getLength(), "ParameterManager::classifyLinks: createFilterConditionFromColumnLink returned nonsense!" );
314 // remember meta information about this new parameter
315 ::std::pair< ParameterInformation::iterator, bool > aInsertionPos =
316 m_aParameterInformation.insert(
317 ParameterInformation::value_type( sNewParamName, ParameterMetaData( NULL ) )
319 OSL_ENSURE( aInsertionPos.second, "ParameterManager::classifyLinks: there already was a parameter with this name!" );
320 aInsertionPos.first->second.eType = eLinkedByColumnName;
322 // remember the filter component
323 _out_rAdditionalFilterComponents.push_back( sFilterCondition );
325 // remember the new "detail field" for this link
326 aStrippedDetailFields.push_back( sNewParamName );
327 bNeedExchangeLinks = true;
329 else
331 // the detail field neither denotes a column name, nor a parameter name
332 bValidLink = false;
333 bNeedExchangeLinks = true;
337 if ( bValidLink )
338 aStrippedMasterFields.push_back( *pMasterFields );
340 OSL_POSTCOND( aStrippedMasterFields.size() == aStrippedDetailFields.size(),
341 "ParameterManager::classifyLinks: inconsistency in new link pairs!" );
343 if ( bNeedExchangeLinks )
345 ::rtl::OUString *pFields = aStrippedMasterFields.empty() ? 0 : &aStrippedMasterFields[0];
346 m_aMasterFields = Sequence< ::rtl::OUString >( pFields, aStrippedMasterFields.size() );
347 pFields = aStrippedDetailFields.empty() ? 0 : &aStrippedDetailFields[0];
348 m_aDetailFields = Sequence< ::rtl::OUString >( pFields, aStrippedDetailFields.size() );
352 //--------------------------------------------------------------------
353 void ParameterManager::analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails )
355 OSL_PRECOND( isAlive(), "ParameterManager::analyzeFieldLinks: not initialized, or already disposed!" );
356 if ( !isAlive() )
357 return;
359 _rColumnsInLinkDetails = false;
362 // the links as determined by the properties
363 Reference< XPropertySet > xProp = m_xComponent;
364 OSL_ENSURE(xProp.is(),"Some already released my component!");
365 if ( xProp.is() )
367 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MASTERFIELDS) ) >>= m_aMasterFields;
368 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DETAILFIELDS) ) >>= m_aDetailFields;
372 // normalize to equal length
373 sal_Int32 nMasterLength = m_aMasterFields.getLength();
374 sal_Int32 nDetailLength = m_aDetailFields.getLength();
376 if ( nMasterLength > nDetailLength )
377 m_aMasterFields.realloc( nDetailLength );
378 else if ( nDetailLength > nMasterLength )
379 m_aDetailFields.realloc( nMasterLength );
382 Reference< XNameAccess > xColumns;
383 if ( !getColumns( xColumns, true ) )
384 // already asserted in getColumns
385 return;
387 Reference< XNameAccess > xParentColumns;
388 if ( !getParentColumns( xParentColumns, true ) )
389 return;
391 // classify the links - depending on what the detail fields in each link pair denotes
392 ::std::vector< ::rtl::OUString > aAdditionalFilterComponents;
393 classifyLinks( xParentColumns, xColumns, aAdditionalFilterComponents );
395 // did we find links where the detail field refers to a detail column (instead of a parameter name)?
396 if ( !aAdditionalFilterComponents.empty() )
398 const static ::rtl::OUString s_sAnd( RTL_CONSTASCII_USTRINGPARAM( " AND " ) );
399 // build a conjunction of all the filter components
400 ::rtl::OUStringBuffer sAdditionalFilter;
401 for ( ::std::vector< ::rtl::OUString >::const_iterator aComponent = aAdditionalFilterComponents.begin();
402 aComponent != aAdditionalFilterComponents.end();
403 ++aComponent
406 if ( sAdditionalFilter.getLength() )
407 sAdditionalFilter.append(s_sAnd);
409 sAdditionalFilter.appendAscii("( ",((sal_Int32)(sizeof("( ")-1)));
410 sAdditionalFilter.append(*aComponent);
411 sAdditionalFilter.appendAscii(" )",((sal_Int32)(sizeof(" )")-1)));
414 // now set this filter at the 's filter manager
415 _rFilterManager.setFilterComponent( FilterManager::fcLinkFilter, sAdditionalFilter.makeStringAndClear() );
417 _rColumnsInLinkDetails = true;
420 catch( const Exception& )
422 OSL_ENSURE( sal_False, "ParameterManager::analyzeFieldLinks: caught an exception!" );
426 //--------------------------------------------------------------------
427 void ParameterManager::createOuterParameters()
429 OSL_PRECOND( !m_pOuterParameters.is(), "ParameterManager::createOuterParameters: outer parameters not initialized!" );
430 OSL_PRECOND( m_xInnerParamUpdate.is(), "ParameterManager::createOuterParameters: no write access to the inner parameters!" );
431 if ( !m_xInnerParamUpdate.is() )
432 return;
434 m_pOuterParameters = new param::ParameterWrapperContainer;
436 #if OSL_DEBUG_LEVEL > 0
437 sal_Int32 nSmallestIndexLinkedByColumnName = -1;
438 sal_Int32 nLargestIndexNotLinkedByColumnName = -1;
439 #endif
440 ::rtl::OUString sName;
441 for ( ParameterInformation::iterator aParam = m_aParameterInformation.begin();
442 aParam != m_aParameterInformation.end();
443 ++aParam
446 #if OSL_DEBUG_LEVEL > 0
447 if ( aParam->second.aInnerIndexes.size() )
448 if ( aParam->second.eType == eLinkedByColumnName )
450 if ( nSmallestIndexLinkedByColumnName == -1 )
451 nSmallestIndexLinkedByColumnName = aParam->second.aInnerIndexes[ 0 ];
453 else
455 nLargestIndexNotLinkedByColumnName = aParam->second.aInnerIndexes[ aParam->second.aInnerIndexes.size() - 1 ];
457 #endif
458 if ( aParam->second.eType != eFilledExternally )
459 continue;
461 // check which of the parameters have already been visited (e.g. filled via XParameters)
462 size_t nAlreadyVisited = 0;
463 for ( ::std::vector< sal_Int32 >::iterator aIndex = aParam->second.aInnerIndexes.begin();
464 aIndex != aParam->second.aInnerIndexes.end();
465 ++aIndex
468 if ( ( m_aParametersVisited.size() > (size_t)*aIndex ) && m_aParametersVisited[ *aIndex ] )
469 { // exclude this index
470 *aIndex = -1;
471 ++nAlreadyVisited;
474 if ( nAlreadyVisited == aParam->second.aInnerIndexes.size() )
475 continue;
477 // need a wrapper for this .... the "inner parameters" as supplied by a result set don't have a "Value"
478 // property, but the parameter listeners expect such a property. So we need an object "aggregating"
479 // xParam and supplying an additional property ("Value")
480 // (it's no real aggregation of course ...)
481 m_pOuterParameters->push_back( new param::ParameterWrapper( aParam->second.xComposerColumn, m_xInnerParamUpdate, aParam->second.aInnerIndexes ) );
484 #if OSL_DEBUG_LEVEL > 0
485 OSL_ENSURE( ( nSmallestIndexLinkedByColumnName == -1 ) || ( nLargestIndexNotLinkedByColumnName == -1 ) ||
486 ( nSmallestIndexLinkedByColumnName > nLargestIndexNotLinkedByColumnName ),
487 "ParameterManager::createOuterParameters: inconsistency!" );
489 // for the master-detail links, where the detail field denoted a column name, we created an addtional ("artificial")
490 // filter, and *appended* it to all other (potentially) existing filters of the row set. This means that the indexes
491 // for the parameters resulting from the artifical filter should be larger than any other parameter index, and this
492 // is what the assertion checks.
493 // If the assertion fails, then we would need another handling for the "parameters visited" flags, since they're based
494 // on parameter indexes *without* the artificial filter (because this filter is not visible from the outside).
495 #endif
498 //--------------------------------------------------------------------
499 void ParameterManager::updateParameterInfo( FilterManager& _rFilterManager )
501 OSL_PRECOND( isAlive(), "ParameterManager::updateParameterInfo: not initialized, or already disposed!" );
502 if ( !isAlive() )
503 return;
505 clearAllParameterInformation();
506 cacheConnectionInfo();
508 // check whether the is based on a statement/query which requires parameters
509 Reference< XPropertySet > xProp = m_xComponent;
510 OSL_ENSURE(xProp.is(),"Some already released my component!");
511 if ( xProp.is() )
513 if ( !initializeComposerByComponent( xProp ) )
514 { // okay, nothing to do
515 m_bUpToDate = true;
516 return;
517 } // if ( !initializeComposerByComponent( m_xComponent ) )
519 OSL_POSTCOND( m_xInnerParamColumns.is(), "ParameterManager::updateParameterInfo: initializeComposerByComponent did nonsense (1)!" );
521 // collect all parameters which are defined by the "inner parameters"
522 collectInnerParameters( false );
524 // analyze the master-detail relationships
525 bool bColumnsInLinkDetails = false;
526 analyzeFieldLinks( _rFilterManager, bColumnsInLinkDetails );
528 if ( bColumnsInLinkDetails )
530 // okay, in this case, analyzeFieldLinks modified the "real" filter at the RowSet, to contain
531 // an additional restriction (which we created ourself)
532 // So we need to update all information about our inner parameter columns
533 Reference< XPropertySet > xDirectRowSetProps;
534 m_xAggregatedRowSet->queryAggregation( ::getCppuType( &xDirectRowSetProps ) ) >>= xDirectRowSetProps;
535 OSL_VERIFY( initializeComposerByComponent( xDirectRowSetProps ) );
536 collectInnerParameters( true );
539 if ( !m_nInnerCount )
540 { // no parameters at all
541 m_bUpToDate = true;
542 return;
545 // for what now remains as outer parameters, create the wrappers for the single
546 // parameter columns
547 createOuterParameters();
549 m_bUpToDate = true;
552 //--------------------------------------------------------------------
553 void ParameterManager::fillLinkedParameters( const Reference< XNameAccess >& _rxParentColumns )
555 OSL_PRECOND( isAlive(), "ParameterManager::fillLinkedParameters: not initialized, or already disposed!" );
556 if ( !isAlive() )
557 return;
558 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::fillLinkedParameters: no inner parameters found!" );
559 OSL_ENSURE ( _rxParentColumns.is(), "ParameterManager::fillLinkedParameters: invalid parent columns!" );
563 // the master and detail field( name)s of the
564 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray();
565 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray();
567 sal_Int32 nMasterLen = m_aMasterFields.getLength();
568 Any aParamType, aScale, aValue;
570 // loop through all master fields. For each of them, get the respective column from the
571 // parent , and forward it's current value as paramter value to the (inner) row set
572 for ( sal_Int32 i = 0; i < nMasterLen; ++i, ++pMasterFields, ++pDetailFields )
574 // does the name denote a valid column in the parent?
575 if ( !_rxParentColumns->hasByName( *pMasterFields ) )
577 OSL_ENSURE( sal_False, "ParameterManager::fillLinkedParameters: invalid master names should have been stripped long before!" );
578 continue;
581 // do we, for this name, know where to place the values?
582 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields );
583 if ( ( aParamInfo == m_aParameterInformation.end() )
584 || ( aParamInfo->second.aInnerIndexes.empty() )
587 OSL_ENSURE( sal_False, "ParameterManager::fillLinkedParameters: nothing known about this detail field!" );
588 continue;
591 // the concrete master field
592 Reference< XPropertySet > xMasterField(_rxParentColumns->getByName( *pMasterFields ),UNO_QUERY);
594 // the positions where we have to fill in values for the current parameter name
595 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin();
596 aPosition != aParamInfo->second.aInnerIndexes.end();
597 ++aPosition
600 // the concrete detail field
601 Reference< XPropertySet > xDetailField(m_xInnerParamColumns->getByIndex( *aPosition ),UNO_QUERY);
602 OSL_ENSURE( xDetailField.is(), "ParameterManager::fillLinkedParameters: invalid detail field!" );
603 if ( !xDetailField.is() )
604 continue;
606 // type and scale of the parameter field
607 sal_Int32 nParamType = DataType::VARCHAR;
608 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nParamType );
610 sal_Int32 nScale = 0;
611 if ( xDetailField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) )
612 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) >>= nScale );
614 // transfer the param value
617 m_xInnerParamUpdate->setObjectWithInfo(
618 *aPosition + 1, // parameters are based at 1
619 xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ),
620 nParamType,
621 nScale
624 catch( const Exception& )
626 OSL_ENSURE( sal_False,
627 ::rtl::OString( "ParameterManager::fillLinkedParameters: master-detail parameter number " )
628 += ::rtl::OString::valueOf( sal_Int32( *aPosition + 1 ) )
629 += ::rtl::OString( " could not be filled!" ) );
634 catch( const Exception& )
636 DBG_UNHANDLED_EXCEPTION();
640 //--------------------------------------------------------------------
641 bool ParameterManager::completeParameters( const Reference< XInteractionHandler >& _rxCompletionHandler, const Reference< XConnection > _rxConnection )
643 OSL_PRECOND( isAlive(), "ParameterManager::completeParameters: not initialized, or already disposed!" );
644 OSL_ENSURE ( _rxCompletionHandler.is(), "ParameterManager::completeParameters: invalid interaction handler!" );
646 // two continuations (Ok and Cancel)
647 OInteractionAbort* pAbort = new OInteractionAbort;
648 OParameterContinuation* pParams = new OParameterContinuation;
650 // the request
651 ParametersRequest aRequest;
652 aRequest.Parameters = m_pOuterParameters.get();
653 aRequest.Connection = _rxConnection;
654 OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aRequest ) );
655 Reference< XInteractionRequest > xRequest( pRequest );
657 // some knittings
658 pRequest->addContinuation( pAbort );
659 pRequest->addContinuation( pParams );
661 // execute the request
664 _rxCompletionHandler->handle( xRequest );
666 catch( const Exception& )
668 OSL_ENSURE( sal_False, "ParameterManager::completeParameters: caught an exception while calling the handler!" );
671 if ( !pParams->wasSelected() )
672 // canceled by the user (i.e. (s)he canceled the dialog)
673 return false;
677 // transfer the values from the continuation object to the parameter columns
678 Sequence< PropertyValue > aFinalValues = pParams->getValues();
679 const PropertyValue* pFinalValues = aFinalValues.getConstArray();
680 for ( sal_Int32 i = 0; i < aFinalValues.getLength(); ++i, ++pFinalValues )
682 Reference< XPropertySet > xParamColumn(aRequest.Parameters->getByIndex( i ),UNO_QUERY);
683 if ( xParamColumn.is() )
685 #ifdef DBG_UTIL
686 ::rtl::OUString sName;
687 xParamColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName;
688 OSL_ENSURE( sName == pFinalValues->Name, "ParameterManager::completeParameters: inconsistent parameter names!" );
689 #endif
690 xParamColumn->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), pFinalValues->Value );
691 // the property sets are wrapper classes, translating the Value property into a call to
692 // the appropriate XParameters interface
696 catch( const Exception& )
698 OSL_ENSURE( sal_False, "ParameterManager::completeParameters: caught an exception while propagating the values!" );
700 return true;
703 //--------------------------------------------------------------------
704 bool ParameterManager::consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies )
706 bool bCanceled = false;
708 sal_Int32 nParamsLeft = m_pOuterParameters->getParameters().size();
709 // TODO: shouldn't we subtract all the parameters which were already visited?
710 if ( nParamsLeft )
712 ::cppu::OInterfaceIteratorHelper aIter( m_aParameterListeners );
713 Reference< XPropertySet > xProp = m_xComponent;
714 OSL_ENSURE(xProp.is(),"Some already released my component!");
715 DatabaseParameterEvent aEvent( xProp.get(), m_pOuterParameters.get() );
717 _rClearForNotifies.clear();
718 while ( aIter.hasMoreElements() && !bCanceled )
719 bCanceled = !static_cast< XDatabaseParameterListener* >( aIter.next() )->approveParameter( aEvent );
720 _rClearForNotifies.reset();
723 return !bCanceled;
726 //--------------------------------------------------------------------
727 bool ParameterManager::fillParameterValues( const Reference< XInteractionHandler >& _rxCompletionHandler, ::osl::ResettableMutexGuard& _rClearForNotifies )
729 OSL_PRECOND( isAlive(), "ParameterManager::fillParameterValues: not initialized, or already disposed!" );
730 if ( !isAlive() )
731 return true;
733 if ( m_nInnerCount == 0 )
734 // no parameters at all
735 return true;
737 // fill the parameters from the master-detail relationship
738 Reference< XNameAccess > xParentColumns;
739 if ( getParentColumns( xParentColumns, false ) && xParentColumns->hasElements() && m_aMasterFields.getLength() )
740 fillLinkedParameters( xParentColumns );
742 // let the user (via the interaction handler) fill all remaining parameters
743 Reference< XConnection > xConnection;
744 getConnection( xConnection );
746 if ( _rxCompletionHandler.is() )
747 return completeParameters( _rxCompletionHandler, xConnection );
749 return consultParameterListeners( _rClearForNotifies );
752 //--------------------------------------------------------------------
753 bool ParameterManager::getConnection( Reference< XConnection >& /* [out] */ _rxConnection )
755 OSL_PRECOND( isAlive(), "ParameterManager::getConnection: not initialized, or already disposed!" );
756 if ( !isAlive() )
757 return false;
759 _rxConnection.clear();
762 Reference< XPropertySet > xProp = m_xComponent;
763 OSL_ENSURE(xProp.is(),"Some already released my component!");
764 if ( xProp.is() )
765 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ACTIVE_CONNECTION) ) >>= _rxConnection;
767 catch( const Exception& )
769 OSL_ENSURE( sal_False, "ParameterManager::getConnection: could not retrieve the connection of the !" );
771 return _rxConnection.is();
774 //--------------------------------------------------------------------
775 void ParameterManager::cacheConnectionInfo() SAL_THROW(( ))
779 Reference< XConnection > xConnection;
780 getConnection( xConnection );
781 Reference< XDatabaseMetaData > xMeta;
782 if ( xConnection.is() )
783 xMeta = xConnection->getMetaData();
784 if ( xMeta.is() )
786 m_sIdentifierQuoteString = xMeta->getIdentifierQuoteString();
787 m_sSpecialCharacters = xMeta->getExtraNameCharacters();
790 catch( const Exception& )
792 OSL_ENSURE( sal_False, "ParameterManager::cacheConnectionInfo: caught an exception!" );
796 //--------------------------------------------------------------------
797 bool ParameterManager::getColumns( Reference< XNameAccess >& /* [out] */ _rxColumns, bool _bFromComposer ) SAL_THROW(( Exception ))
799 _rxColumns.clear();
801 Reference< XColumnsSupplier > xColumnSupp;
802 if ( _bFromComposer )
803 xColumnSupp = xColumnSupp.query( m_xComposer );
804 else
805 xColumnSupp.set( m_xComponent.get(),UNO_QUERY);
806 if ( xColumnSupp.is() )
807 _rxColumns = xColumnSupp->getColumns();
808 OSL_ENSURE( _rxColumns.is(), "ParameterManager::getColumns: could not retrieve the columns for the detail !" );
810 return _rxColumns.is();
813 //--------------------------------------------------------------------
814 bool ParameterManager::getParentColumns( Reference< XNameAccess >& /* [out] */ _out_rxParentColumns, bool _bFromComposer )
816 OSL_PRECOND( isAlive(), "ParameterManager::getParentColumns: not initialized, or already disposed!" );
818 _out_rxParentColumns.clear();
821 // get the parent of the component we're working for
822 Reference< XChild > xAsChild( m_xComponent.get(), UNO_QUERY_THROW );
823 Reference< XPropertySet > xParent( xAsChild->getParent(), UNO_QUERY );
824 if ( !xParent.is() )
825 return false;
827 // the columns supplier: either from a composer, or directly from the
828 Reference< XColumnsSupplier > xParentColSupp;
829 if ( _bFromComposer )
831 // re-create the parent composer all the time. Else, we'd have to bother with
832 // being a listener at its properties, its loaded state, and event the parent-relationship.
833 m_xParentComposer.reset(
834 getCurrentSettingsComposer( xParent, m_xORB ),
835 SharedQueryComposer::TakeOwnership
837 xParentColSupp = xParentColSupp.query( m_xParentComposer );
839 else
840 xParentColSupp = xParentColSupp.query( xParent );
842 // get the columns of the parent
843 if ( xParentColSupp.is() )
844 _out_rxParentColumns = xParentColSupp->getColumns();
846 catch( const Exception& )
848 OSL_ENSURE( sal_False, "ParameterManager::getParentColumns: caught an exception!" );
850 return _out_rxParentColumns.is();
853 //--------------------------------------------------------------------
854 void ParameterManager::addParameterListener( const Reference< XDatabaseParameterListener >& _rxListener )
856 if ( _rxListener.is() )
857 m_aParameterListeners.addInterface( _rxListener );
860 //--------------------------------------------------------------------
861 void ParameterManager::removeParameterListener( const Reference< XDatabaseParameterListener >& _rxListener )
863 m_aParameterListeners.removeInterface( _rxListener );
866 //--------------------------------------------------------------------
867 void ParameterManager::resetParameterValues( ) SAL_THROW(())
869 OSL_PRECOND( isAlive(), "ParameterManager::resetParameterValues: not initialized, or already disposed!" );
870 if ( !isAlive() )
871 return;
873 if ( !m_nInnerCount )
874 // no parameters at all
875 return;
879 Reference< XNameAccess > xColumns;
880 if ( !getColumns( xColumns, false ) )
881 // already asserted in getColumns
882 return;
884 Reference< XNameAccess > xParentColumns;
885 if ( !getParentColumns( xParentColumns, false ) )
886 return;
888 // loop through all links pairs
889 const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray();
890 const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray();
892 Reference< XPropertySet > xMasterField;
893 Reference< XPropertySet > xDetailField;
895 // now really ....
896 const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength();
897 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields )
899 if ( !xParentColumns->hasByName( *pMasterFields ) )
901 // if this name is unknown in the parent columns, then we don't have a source
902 // for copying the value to the detail columns
903 OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: this should have been stripped long before!" );
904 continue;
907 // for all inner parameters which are bound to the name as specified by the
908 // slave element of the link, propagate the value from the master column to this
909 // parameter column
910 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields );
911 if ( ( aParamInfo == m_aParameterInformation.end() )
912 || ( aParamInfo->second.aInnerIndexes.empty() )
915 OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: nothing known about this detail field!" );
916 continue;
919 xParentColumns->getByName( *pMasterFields ) >>= xMasterField;
920 if ( !xMasterField.is() )
921 continue;
923 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin();
924 aPosition != aParamInfo->second.aInnerIndexes.end();
925 ++aPosition
928 Reference< XPropertySet > xInnerParameter;
929 m_xInnerParamColumns->getByIndex( *aPosition ) >>= xInnerParameter;
930 if ( !xInnerParameter.is() )
931 continue;
933 ::rtl::OUString sParamColumnRealName;
934 xInnerParameter->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME) ) >>= sParamColumnRealName;
935 if ( xColumns->hasByName( sParamColumnRealName ) )
936 { // our own columns have a column which's name equals the real name of the param column
937 // -> transfer the value property
938 xColumns->getByName( sParamColumnRealName ) >>= xDetailField;
939 if ( xDetailField.is() )
940 xDetailField->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ) );
945 catch( const Exception& )
947 OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: caught an exception!" );
952 //--------------------------------------------------------------------
953 void ParameterManager::externalParameterVisited( sal_Int32 _nIndex )
955 if ( m_aParametersVisited.size() < (size_t)_nIndex )
957 m_aParametersVisited.reserve( _nIndex );
958 for ( sal_Int32 i = m_aParametersVisited.size(); i < _nIndex; ++i )
959 m_aParametersVisited.push_back( false );
961 m_aParametersVisited[ _nIndex - 1 ] = true;
964 #define VISIT_PARAMETER( method ) \
965 ::osl::MutexGuard aGuard( m_rMutex ); \
966 OSL_ENSURE( m_xInnerParamUpdate.is(), "ParameterManager::XParameters::setXXX: no XParameters access to the RowSet!" ); \
967 if ( !m_xInnerParamUpdate.is() ) \
968 return; \
969 m_xInnerParamUpdate->method; \
970 externalParameterVisited( _nIndex ) \
972 //--------------------------------------------------------------------
973 void ParameterManager::setNull( sal_Int32 _nIndex, sal_Int32 sqlType )
975 VISIT_PARAMETER( setNull( _nIndex, sqlType ) );
978 //--------------------------------------------------------------------
979 void ParameterManager::setObjectNull( sal_Int32 _nIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName )
981 VISIT_PARAMETER( setObjectNull( _nIndex, sqlType, typeName ) );
984 //--------------------------------------------------------------------
985 void ParameterManager::setBoolean( sal_Int32 _nIndex, sal_Bool x )
987 VISIT_PARAMETER( setBoolean( _nIndex, x ) );
990 //--------------------------------------------------------------------
991 void ParameterManager::setByte( sal_Int32 _nIndex, sal_Int8 x )
993 VISIT_PARAMETER( setByte( _nIndex, x ) );
996 //--------------------------------------------------------------------
997 void ParameterManager::setShort( sal_Int32 _nIndex, sal_Int16 x )
999 VISIT_PARAMETER( setShort( _nIndex, x ) );
1002 //--------------------------------------------------------------------
1003 void ParameterManager::setInt( sal_Int32 _nIndex, sal_Int32 x )
1005 VISIT_PARAMETER( setInt( _nIndex, x ) );
1008 //--------------------------------------------------------------------
1009 void ParameterManager::setLong( sal_Int32 _nIndex, sal_Int64 x )
1011 VISIT_PARAMETER( setLong( _nIndex, x ) );
1014 //--------------------------------------------------------------------
1015 void ParameterManager::setFloat( sal_Int32 _nIndex, float x )
1017 VISIT_PARAMETER( setFloat( _nIndex, x ) );
1020 //--------------------------------------------------------------------
1021 void ParameterManager::setDouble( sal_Int32 _nIndex, double x )
1023 VISIT_PARAMETER( setDouble( _nIndex, x ) );
1026 //--------------------------------------------------------------------
1027 void ParameterManager::setString( sal_Int32 _nIndex, const ::rtl::OUString& x )
1029 VISIT_PARAMETER( setString( _nIndex, x ) );
1032 //--------------------------------------------------------------------
1033 void ParameterManager::setBytes( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x )
1035 VISIT_PARAMETER( setBytes( _nIndex, x ) );
1038 //--------------------------------------------------------------------
1039 void ParameterManager::setDate( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x )
1041 VISIT_PARAMETER( setDate( _nIndex, x ) );
1044 //--------------------------------------------------------------------
1045 void ParameterManager::setTime( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x )
1047 VISIT_PARAMETER( setTime( _nIndex, x ) );
1050 //--------------------------------------------------------------------
1051 void ParameterManager::setTimestamp( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x )
1053 VISIT_PARAMETER( setTimestamp( _nIndex, x ) );
1056 //--------------------------------------------------------------------
1057 void ParameterManager::setBinaryStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length )
1059 VISIT_PARAMETER( setBinaryStream( _nIndex, x, length ) );
1062 //--------------------------------------------------------------------
1063 void ParameterManager::setCharacterStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length )
1065 VISIT_PARAMETER( setCharacterStream( _nIndex, x, length ) );
1068 //--------------------------------------------------------------------
1069 void ParameterManager::setObject( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x )
1071 VISIT_PARAMETER( setObject( _nIndex, x ) );
1074 //--------------------------------------------------------------------
1075 void ParameterManager::setObjectWithInfo( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale )
1077 VISIT_PARAMETER( setObjectWithInfo( _nIndex, x, targetSqlType, scale ) );
1080 //--------------------------------------------------------------------
1081 void ParameterManager::setRef( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x )
1083 VISIT_PARAMETER( setRef( _nIndex, x ) );
1086 //--------------------------------------------------------------------
1087 void ParameterManager::setBlob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x )
1089 VISIT_PARAMETER( setBlob( _nIndex, x ) );
1092 //--------------------------------------------------------------------
1093 void ParameterManager::setClob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x )
1095 VISIT_PARAMETER( setClob( _nIndex, x ) );
1098 //--------------------------------------------------------------------
1099 void ParameterManager::setArray( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x )
1101 VISIT_PARAMETER( setArray( _nIndex, x ) );
1104 //--------------------------------------------------------------------
1105 void ParameterManager::clearParameters( )
1107 if ( m_xInnerParamUpdate.is() )
1108 m_xInnerParamUpdate->clearParameters( );
1111 //====================================================================
1112 //= OParameterContinuation
1113 //====================================================================
1114 //--------------------------------------------------------------------
1115 void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw( RuntimeException )
1117 m_aValues = _rValues;
1120 //........................................................................
1121 } // namespace frm
1122 //........................................................................