bump product version to 5.0.4.1
[LibreOffice.git] / connectivity / source / commontools / parameters.cxx
blob1f94a59f1edef957dce2d3a744ab75ae375a0d84
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <connectivity/parameters.hxx>
22 #include <com/sun/star/form/DatabaseParameterEvent.hpp>
23 #include <com/sun/star/sdbc/XParameters.hpp>
24 #include <com/sun/star/container/XChild.hpp>
25 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
26 #include <com/sun/star/container/XEnumerationAccess.hpp>
27 #include <com/sun/star/sdb/XParametersSupplier.hpp>
28 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
29 #include <com/sun/star/sdb/ParametersRequest.hpp>
31 #include <connectivity/dbtools.hxx>
32 #include <connectivity/filtermanager.hxx>
33 #include "TConnection.hxx"
35 #include <tools/diagnose_ex.h>
37 #include <comphelper/uno3.hxx>
38 #include <comphelper/proparrhlp.hxx>
39 #include <comphelper/broadcasthelper.hxx>
40 #include <connectivity/ParameterCont.hxx>
41 #include <rtl/ustrbuf.hxx>
43 namespace dbtools
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::sdb;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::sdbcx;
49 using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::task;
52 using namespace ::com::sun::star::form;
53 using namespace ::com::sun::star::container;
55 using namespace ::comphelper;
56 using namespace ::connectivity;
58 ParameterManager::ParameterManager( ::osl::Mutex& _rMutex, const Reference< XComponentContext >& _rxContext )
59 :m_rMutex ( _rMutex )
60 ,m_aParameterListeners( _rMutex )
61 ,m_xContext ( _rxContext )
62 ,m_pOuterParameters ( NULL )
63 ,m_nInnerCount ( 0 )
64 ,m_bUpToDate ( false )
66 OSL_ENSURE( m_xContext.is(), "ParameterManager::ParameterManager: no service factory!" );
70 void ParameterManager::initialize( const Reference< XPropertySet >& _rxComponent, const Reference< XAggregation >& _rxComponentAggregate )
72 OSL_ENSURE( !m_xComponent.get().is(), "ParameterManager::initialize: already initialized!" );
74 m_xComponent = _rxComponent;
75 m_xAggregatedRowSet = _rxComponentAggregate;
76 if ( m_xAggregatedRowSet.is() )
77 m_xAggregatedRowSet->queryAggregation( cppu::UnoType<decltype(m_xInnerParamUpdate)>::get() ) >>= m_xInnerParamUpdate;
78 OSL_ENSURE( m_xComponent.get().is() && m_xInnerParamUpdate.is(), "ParameterManager::initialize: invalid arguments!" );
79 if ( !m_xComponent.get().is() || !m_xInnerParamUpdate.is() )
80 return;
84 void ParameterManager::dispose( )
86 clearAllParameterInformation();
88 m_xComposer.clear();
89 m_xParentComposer.clear();
90 //m_xComponent.clear();
91 m_xInnerParamUpdate.clear();
92 m_xAggregatedRowSet.clear();
96 void ParameterManager::clearAllParameterInformation()
98 m_xInnerParamColumns.clear();
99 if ( m_pOuterParameters.is() )
100 m_pOuterParameters->dispose();
101 m_pOuterParameters = NULL;
102 m_nInnerCount = 0;
103 ParameterInformation aEmptyInfo;
104 m_aParameterInformation.swap( aEmptyInfo );
105 m_aMasterFields.realloc( 0 );
106 m_aDetailFields.realloc( 0 );
107 m_sIdentifierQuoteString.clear();
108 m_sSpecialCharacters.clear();
109 m_xConnectionMetadata.clear();
110 ::std::vector< bool > aEmptyArray;
111 m_aParametersVisited.swap( aEmptyArray );
112 m_bUpToDate = false;
116 void ParameterManager::setAllParametersNull()
118 OSL_PRECOND( isAlive(), "ParameterManager::setAllParametersNull: not initialized, or already disposed!" );
119 if ( !isAlive() )
120 return;
122 for ( sal_Int32 i = 1; i <= m_nInnerCount; ++i )
123 m_xInnerParamUpdate->setNull( i, DataType::VARCHAR );
127 bool ParameterManager::initializeComposerByComponent( const Reference< XPropertySet >& _rxComponent )
129 OSL_PRECOND( _rxComponent.is(), "ParameterManager::initializeComposerByComponent: invalid !" );
131 m_xComposer.clear();
132 m_xInnerParamColumns.clear();
133 m_nInnerCount = 0;
135 // create and fill a composer
138 // get a query composer for the 's settings
139 m_xComposer.reset( getCurrentSettingsComposer( _rxComponent, m_xContext ), SharedQueryComposer::TakeOwnership );
141 // see if the composer found parameters
142 Reference< XParametersSupplier > xParamSupp( m_xComposer, UNO_QUERY );
143 if ( xParamSupp.is() )
144 m_xInnerParamColumns = xParamSupp->getParameters();
146 if ( m_xInnerParamColumns.is() )
147 m_nInnerCount = m_xInnerParamColumns->getCount();
149 catch( const SQLException& )
153 return m_xInnerParamColumns.is();
157 void ParameterManager::collectInnerParameters( bool _bSecondRun )
159 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::collectInnerParameters: missing some internal data!" );
160 if ( !m_xInnerParamColumns.is() )
161 return;
163 // strip previous index information
164 if ( _bSecondRun )
166 for ( ParameterInformation::iterator aParamInfo = m_aParameterInformation.begin();
167 aParamInfo != m_aParameterInformation.end();
168 ++aParamInfo
171 aParamInfo->second.aInnerIndexes.clear();
175 // we need to map the parameter names (which is all we get from the 's
176 // MasterFields property) to indices, which are needed by the XParameters
177 // interface of the row set)
178 Reference<XPropertySet> xParam;
179 for ( sal_Int32 i = 0; i < m_nInnerCount; ++i )
183 xParam.clear();
184 m_xInnerParamColumns->getByIndex( i ) >>= xParam;
186 OUString sName;
187 xParam->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName;
189 // only append additional parameters when they are not already in the list
190 ParameterInformation::iterator aExistentPos = m_aParameterInformation.find( sName );
191 OSL_ENSURE( !_bSecondRun || ( aExistentPos != m_aParameterInformation.end() ),
192 "ParameterManager::collectInnerParameters: the parameter information should already exist in the second run!" );
194 if ( aExistentPos == m_aParameterInformation.end() )
196 aExistentPos = m_aParameterInformation.insert( ParameterInformation::value_type(
197 sName, xParam ) ).first;
199 else
200 aExistentPos->second.xComposerColumn = xParam;
202 aExistentPos->second.aInnerIndexes.push_back( i );
204 catch( const Exception& )
206 SAL_WARN( "connectivity.commontools", "ParameterManager::collectInnerParameters: caught an exception!" );
212 OUString ParameterManager::createFilterConditionFromColumnLink(
213 const OUString &_rMasterColumn, const Reference < XPropertySet > &xDetailField, OUString &o_rNewParamName )
215 OUString sFilter;
216 // format is:
217 // <detail_column> = :<new_param_name>
219 OUString tblName;
220 xDetailField->getPropertyValue("TableName") >>= tblName;
221 if (!tblName.isEmpty())
222 sFilter = ::dbtools::quoteTableName( m_xConnectionMetadata, tblName, ::dbtools::eInDataManipulation ) + ".";
225 OUString colName;
226 xDetailField->getPropertyValue("RealName") >>= colName;
227 sFilter += quoteName( m_sIdentifierQuoteString, colName ) + " = :";
230 // generate a parameter name which is not already used
231 o_rNewParamName = "link_from_";
232 o_rNewParamName += convertName2SQLName( _rMasterColumn, m_sSpecialCharacters );
233 while ( m_aParameterInformation.find( o_rNewParamName ) != m_aParameterInformation.end() )
235 o_rNewParamName += "_";
238 return sFilter += o_rNewParamName;
242 void ParameterManager::classifyLinks( const Reference< XNameAccess >& _rxParentColumns,
243 const Reference< XNameAccess >& _rxColumns, ::std::vector< OUString >& _out_rAdditionalFilterComponents )
245 OSL_PRECOND( m_aMasterFields.getLength() == m_aDetailFields.getLength(),
246 "ParameterManager::classifyLinks: master and detail fields should have the same length!" );
247 OSL_ENSURE( _rxColumns.is(), "ParameterManager::classifyLinks: invalid columns!" );
249 if ( !_rxColumns.is() )
250 return;
252 // we may need to strip any links which are invalid, so here go the containers
253 // for temporarirly holding the new pairs
254 ::std::vector< OUString > aStrippedMasterFields;
255 ::std::vector< OUString > aStrippedDetailFields;
257 bool bNeedExchangeLinks = false;
259 // classify the links
260 const OUString* pMasterFields = m_aMasterFields.getConstArray();
261 const OUString* pDetailFields = m_aDetailFields.getConstArray();
262 const OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength();
263 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields )
265 if ( pMasterFields->isEmpty() || pDetailFields->isEmpty() )
266 continue;
268 // if not even the master part of the relationship exists in the parent , the
269 // link is invalid as a whole
270 // #i63674# / 2006-03-28 / frank.schoenheit@sun.com
271 if ( !_rxParentColumns->hasByName( *pMasterFields ) )
273 bNeedExchangeLinks = true;
274 continue;
277 bool bValidLink = true;
279 // is there an inner parameter with this name? That is, a parameter which is already part of
280 // the very original statement (not the one we create ourselve, with the additional parameters)
281 ParameterInformation::iterator aPos = m_aParameterInformation.find( *pDetailFields );
282 if ( aPos != m_aParameterInformation.end() )
283 { // there is an inner parameter with this name
284 aPos->second.eType = eLinkedByParamName;
285 aStrippedDetailFields.push_back( *pDetailFields );
287 else
289 // does the detail name denote a column?
290 if ( _rxColumns->hasByName( *pDetailFields ) )
292 Reference< XPropertySet > xDetailField(_rxColumns->getByName( *pDetailFields ), UNO_QUERY);
293 assert(xDetailField.is());
295 OUString sNewParamName;
296 const OUString sFilterCondition = createFilterConditionFromColumnLink( *pMasterFields, xDetailField, sNewParamName );
297 OSL_PRECOND( !sNewParamName.isEmpty(), "ParameterManager::classifyLinks: createFilterConditionFromColumnLink returned nonsense!" );
299 // remember meta information about this new parameter
300 ::std::pair< ParameterInformation::iterator, bool > aInsertionPos =
301 m_aParameterInformation.insert(
302 ParameterInformation::value_type( sNewParamName, ParameterMetaData( NULL ) )
304 OSL_ENSURE( aInsertionPos.second, "ParameterManager::classifyLinks: there already was a parameter with this name!" );
305 aInsertionPos.first->second.eType = eLinkedByColumnName;
307 // remember the filter component
308 _out_rAdditionalFilterComponents.push_back( sFilterCondition );
310 // remember the new "detail field" for this link
311 aStrippedDetailFields.push_back( sNewParamName );
312 bNeedExchangeLinks = true;
314 else
316 // the detail field neither denotes a column name, nor a parameter name
317 bValidLink = false;
318 bNeedExchangeLinks = true;
322 if ( bValidLink )
323 aStrippedMasterFields.push_back( *pMasterFields );
325 SAL_WARN_IF( aStrippedMasterFields.size() != aStrippedDetailFields.size(),
326 "connectivity.commontools",
327 "ParameterManager::classifyLinks: inconsistency in new link pairs!" );
329 if ( bNeedExchangeLinks )
331 m_aMasterFields = Sequence< OUString >( aStrippedMasterFields.data(), aStrippedMasterFields.size() );
332 m_aDetailFields = Sequence< OUString >( aStrippedDetailFields.data(), aStrippedDetailFields.size() );
337 void ParameterManager::analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails )
339 OSL_PRECOND( isAlive(), "ParameterManager::analyzeFieldLinks: not initialized, or already disposed!" );
340 if ( !isAlive() )
341 return;
343 _rColumnsInLinkDetails = false;
346 // the links as determined by the properties
347 Reference< XPropertySet > xProp = m_xComponent;
348 OSL_ENSURE(xProp.is(),"Some already released my component!");
349 if ( xProp.is() )
351 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MASTERFIELDS) ) >>= m_aMasterFields;
352 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DETAILFIELDS) ) >>= m_aDetailFields;
356 // normalize to equal length
357 sal_Int32 nMasterLength = m_aMasterFields.getLength();
358 sal_Int32 nDetailLength = m_aDetailFields.getLength();
360 if ( nMasterLength > nDetailLength )
361 m_aMasterFields.realloc( nDetailLength );
362 else if ( nDetailLength > nMasterLength )
363 m_aDetailFields.realloc( nMasterLength );
366 Reference< XNameAccess > xColumns;
367 if ( !getColumns( xColumns, true ) )
368 // already asserted in getColumns
369 return;
371 Reference< XNameAccess > xParentColumns;
372 if ( !getParentColumns( xParentColumns, true ) )
373 return;
375 // classify the links - depending on what the detail fields in each link pair denotes
376 ::std::vector< OUString > aAdditionalFilterComponents;
377 classifyLinks( xParentColumns, xColumns, aAdditionalFilterComponents );
379 // did we find links where the detail field refers to a detail column (instead of a parameter name)?
380 if ( !aAdditionalFilterComponents.empty() )
382 // build a conjunction of all the filter components
383 OUStringBuffer sAdditionalFilter;
384 for ( ::std::vector< OUString >::const_iterator aComponent = aAdditionalFilterComponents.begin();
385 aComponent != aAdditionalFilterComponents.end();
386 ++aComponent
389 if ( !sAdditionalFilter.isEmpty() )
390 sAdditionalFilter.append(" AND ");
392 sAdditionalFilter.appendAscii("( ",((sal_Int32)(sizeof("( ")-1)));
393 sAdditionalFilter.append(*aComponent);
394 sAdditionalFilter.appendAscii(" )",((sal_Int32)(sizeof(" )")-1)));
397 // now set this filter at the 's filter manager
398 _rFilterManager.setFilterComponent( FilterManager::fcLinkFilter, sAdditionalFilter.makeStringAndClear() );
400 _rColumnsInLinkDetails = true;
403 catch( const Exception& )
405 SAL_WARN( "connectivity.commontools", "ParameterManager::analyzeFieldLinks: caught an exception!" );
410 void ParameterManager::createOuterParameters()
412 OSL_PRECOND( !m_pOuterParameters.is(), "ParameterManager::createOuterParameters: outer parameters not initialized!" );
413 OSL_PRECOND( m_xInnerParamUpdate.is(), "ParameterManager::createOuterParameters: no write access to the inner parameters!" );
414 if ( !m_xInnerParamUpdate.is() )
415 return;
417 m_pOuterParameters = new param::ParameterWrapperContainer;
419 #if OSL_DEBUG_LEVEL > 0
420 sal_Int32 nSmallestIndexLinkedByColumnName = -1;
421 sal_Int32 nLargestIndexNotLinkedByColumnName = -1;
422 #endif
423 for ( ParameterInformation::iterator aParam = m_aParameterInformation.begin();
424 aParam != m_aParameterInformation.end();
425 ++aParam
428 #if OSL_DEBUG_LEVEL > 0
429 if ( aParam->second.aInnerIndexes.size() )
431 if ( aParam->second.eType == eLinkedByColumnName )
433 if ( nSmallestIndexLinkedByColumnName == -1 )
434 nSmallestIndexLinkedByColumnName = aParam->second.aInnerIndexes[ 0 ];
436 else
438 nLargestIndexNotLinkedByColumnName = aParam->second.aInnerIndexes[ aParam->second.aInnerIndexes.size() - 1 ];
441 #endif
442 if ( aParam->second.eType != eFilledExternally )
443 continue;
445 // check which of the parameters have already been visited (e.g. filled via XParameters)
446 size_t nAlreadyVisited = 0;
447 for ( ::std::vector< sal_Int32 >::iterator aIndex = aParam->second.aInnerIndexes.begin();
448 aIndex != aParam->second.aInnerIndexes.end();
449 ++aIndex
452 if ( ( m_aParametersVisited.size() > (size_t)*aIndex ) && m_aParametersVisited[ *aIndex ] )
453 { // exclude this index
454 *aIndex = -1;
455 ++nAlreadyVisited;
458 if ( nAlreadyVisited == aParam->second.aInnerIndexes.size() )
459 continue;
461 // need a wrapper for this .... the "inner parameters" as supplied by a result set don't have a "Value"
462 // property, but the parameter listeners expect such a property. So we need an object "aggregating"
463 // xParam and supplying an additional property ("Value")
464 // (it's no real aggregation of course ...)
465 m_pOuterParameters->push_back( new param::ParameterWrapper( aParam->second.xComposerColumn, m_xInnerParamUpdate, aParam->second.aInnerIndexes ) );
468 #if OSL_DEBUG_LEVEL > 0
469 OSL_ENSURE( ( nSmallestIndexLinkedByColumnName == -1 ) || ( nLargestIndexNotLinkedByColumnName == -1 ) ||
470 ( nSmallestIndexLinkedByColumnName > nLargestIndexNotLinkedByColumnName ),
471 "ParameterManager::createOuterParameters: inconsistency!" );
473 // for the master-detail links, where the detail field denoted a column name, we created an additional ("artificial")
474 // filter, and *appended* it to all other (potentially) existing filters of the row set. This means that the indexes
475 // for the parameters resulting from the artificial filter should be larger than any other parameter index, and this
476 // is what the assertion checks.
477 // If the assertion fails, then we would need another handling for the "parameters visited" flags, since they're based
478 // on parameter indexes *without* the artificial filter (because this filter is not visible from the outside).
479 #endif
483 void ParameterManager::updateParameterInfo( FilterManager& _rFilterManager )
485 OSL_PRECOND( isAlive(), "ParameterManager::updateParameterInfo: not initialized, or already disposed!" );
486 if ( !isAlive() )
487 return;
489 clearAllParameterInformation();
490 cacheConnectionInfo();
492 // check whether the is based on a statement/query which requires parameters
493 Reference< XPropertySet > xProp = m_xComponent;
494 OSL_ENSURE(xProp.is(),"Some already released my component!");
495 if ( xProp.is() )
497 if ( !initializeComposerByComponent( xProp ) )
498 { // okay, nothing to do
499 m_bUpToDate = true;
500 return;
501 } // if ( !initializeComposerByComponent( m_xComponent ) )
503 SAL_WARN_IF( !m_xInnerParamColumns.is(),
504 "connectivity.commontools",
505 "ParameterManager::updateParameterInfo: initializeComposerByComponent did nonsense (1)!" );
507 // collect all parameters which are defined by the "inner parameters"
508 collectInnerParameters( false );
510 // analyze the master-detail relationships
511 bool bColumnsInLinkDetails = false;
512 analyzeFieldLinks( _rFilterManager, bColumnsInLinkDetails );
514 if ( bColumnsInLinkDetails )
516 // okay, in this case, analyzeFieldLinks modified the "real" filter at the RowSet, to contain
517 // an additional restriction (which we created ourself)
518 // So we need to update all information about our inner parameter columns
519 Reference< XPropertySet > xDirectRowSetProps;
520 m_xAggregatedRowSet->queryAggregation( cppu::UnoType<decltype(xDirectRowSetProps)>::get() ) >>= xDirectRowSetProps;
521 OSL_VERIFY( initializeComposerByComponent( xDirectRowSetProps ) );
522 collectInnerParameters( true );
525 if ( !m_nInnerCount )
526 { // no parameters at all
527 m_bUpToDate = true;
528 return;
531 // for what now remains as outer parameters, create the wrappers for the single
532 // parameter columns
533 createOuterParameters();
535 m_bUpToDate = true;
539 void ParameterManager::fillLinkedParameters( const Reference< XNameAccess >& _rxParentColumns )
541 OSL_PRECOND( isAlive(), "ParameterManager::fillLinkedParameters: not initialized, or already disposed!" );
542 if ( !isAlive() )
543 return;
544 OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::fillLinkedParameters: no inner parameters found!" );
545 OSL_ENSURE ( _rxParentColumns.is(), "ParameterManager::fillLinkedParameters: invalid parent columns!" );
549 // the master and detail field( name)s of the
550 const OUString* pMasterFields = m_aMasterFields.getConstArray();
551 const OUString* pDetailFields = m_aDetailFields.getConstArray();
553 sal_Int32 nMasterLen = m_aMasterFields.getLength();
555 // loop through all master fields. For each of them, get the respective column from the
556 // parent , and forward its current value as parameter value to the (inner) row set
557 for ( sal_Int32 i = 0; i < nMasterLen; ++i, ++pMasterFields, ++pDetailFields )
559 // does the name denote a valid column in the parent?
560 if ( !_rxParentColumns->hasByName( *pMasterFields ) )
562 SAL_WARN( "connectivity.commontools", "ParameterManager::fillLinkedParameters: invalid master names should have been stripped long before!" );
563 continue;
566 // do we, for this name, know where to place the values?
567 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields );
568 if ( ( aParamInfo == m_aParameterInformation.end() )
569 || ( aParamInfo->second.aInnerIndexes.empty() )
572 SAL_WARN( "connectivity.commontools", "ParameterManager::fillLinkedParameters: nothing known about this detail field!" );
573 continue;
576 // the concrete master field
577 Reference< XPropertySet > xMasterField(_rxParentColumns->getByName( *pMasterFields ),UNO_QUERY);
579 // the positions where we have to fill in values for the current parameter name
580 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin();
581 aPosition != aParamInfo->second.aInnerIndexes.end();
582 ++aPosition
585 // the concrete detail field
586 Reference< XPropertySet > xDetailField(m_xInnerParamColumns->getByIndex( *aPosition ),UNO_QUERY);
587 OSL_ENSURE( xDetailField.is(), "ParameterManager::fillLinkedParameters: invalid detail field!" );
588 if ( !xDetailField.is() )
589 continue;
591 // type and scale of the parameter field
592 sal_Int32 nParamType = DataType::VARCHAR;
593 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nParamType );
595 sal_Int32 nScale = 0;
596 if ( xDetailField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) )
597 OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) >>= nScale );
599 // transfer the param value
602 m_xInnerParamUpdate->setObjectWithInfo(
603 *aPosition + 1, // parameters are based at 1
604 xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ),
605 nParamType,
606 nScale
609 catch( const Exception& )
611 DBG_UNHANDLED_EXCEPTION();
612 SAL_WARN( "connectivity.commontools", "ParameterManager::fillLinkedParameters: master-detail parameter number " <<
613 sal_Int32( *aPosition + 1 ) << " could not be filled!" );
618 catch( const Exception& )
620 DBG_UNHANDLED_EXCEPTION();
625 bool ParameterManager::completeParameters( const Reference< XInteractionHandler >& _rxCompletionHandler, const Reference< XConnection >& _rxConnection )
627 OSL_PRECOND( isAlive(), "ParameterManager::completeParameters: not initialized, or already disposed!" );
628 OSL_ENSURE ( _rxCompletionHandler.is(), "ParameterManager::completeParameters: invalid interaction handler!" );
630 // two continuations (Ok and Cancel)
631 OInteractionAbort* pAbort = new OInteractionAbort;
632 OParameterContinuation* pParams = new OParameterContinuation;
634 // the request
635 ParametersRequest aRequest;
636 aRequest.Parameters = m_pOuterParameters.get();
637 aRequest.Connection = _rxConnection;
638 OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aRequest ) );
639 Reference< XInteractionRequest > xRequest( pRequest );
641 // some knittings
642 pRequest->addContinuation( pAbort );
643 pRequest->addContinuation( pParams );
645 // execute the request
648 _rxCompletionHandler->handle( xRequest );
650 catch( const Exception& )
652 SAL_WARN( "connectivity.commontools", "ParameterManager::completeParameters: caught an exception while calling the handler!" );
655 if ( !pParams->wasSelected() )
656 // canceled by the user (i.e. (s)he canceled the dialog)
657 return false;
661 // transfer the values from the continuation object to the parameter columns
662 Sequence< PropertyValue > aFinalValues = pParams->getValues();
663 const PropertyValue* pFinalValues = aFinalValues.getConstArray();
664 for ( sal_Int32 i = 0; i < aFinalValues.getLength(); ++i, ++pFinalValues )
666 Reference< XPropertySet > xParamColumn(aRequest.Parameters->getByIndex( i ),UNO_QUERY);
667 if ( xParamColumn.is() )
669 #ifdef DBG_UTIL
670 OUString sName;
671 xParamColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName;
672 OSL_ENSURE( sName == pFinalValues->Name, "ParameterManager::completeParameters: inconsistent parameter names!" );
673 #endif
674 xParamColumn->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), pFinalValues->Value );
675 // the property sets are wrapper classes, translating the Value property into a call to
676 // the appropriate XParameters interface
680 catch( const Exception& )
682 SAL_WARN( "connectivity.commontools", "ParameterManager::completeParameters: caught an exception while propagating the values!" );
684 return true;
688 bool ParameterManager::consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies )
690 bool bCanceled = false;
692 sal_Int32 nParamsLeft = m_pOuterParameters->getParameters().size();
693 // TODO: shouldn't we subtract all the parameters which were already visited?
694 if ( nParamsLeft )
696 ::cppu::OInterfaceIteratorHelper aIter( m_aParameterListeners );
697 Reference< XPropertySet > xProp = m_xComponent;
698 OSL_ENSURE(xProp.is(),"Some already released my component!");
699 DatabaseParameterEvent aEvent( xProp.get(), m_pOuterParameters.get() );
701 _rClearForNotifies.clear();
702 while ( aIter.hasMoreElements() && !bCanceled )
703 bCanceled = !static_cast< XDatabaseParameterListener* >( aIter.next() )->approveParameter( aEvent );
704 _rClearForNotifies.reset();
707 return !bCanceled;
711 bool ParameterManager::fillParameterValues( const Reference< XInteractionHandler >& _rxCompletionHandler, ::osl::ResettableMutexGuard& _rClearForNotifies )
713 OSL_PRECOND( isAlive(), "ParameterManager::fillParameterValues: not initialized, or already disposed!" );
714 if ( !isAlive() )
715 return true;
717 if ( m_nInnerCount == 0 )
718 // no parameters at all
719 return true;
721 // fill the parameters from the master-detail relationship
722 Reference< XNameAccess > xParentColumns;
723 if ( getParentColumns( xParentColumns, false ) && xParentColumns->hasElements() && m_aMasterFields.getLength() )
724 fillLinkedParameters( xParentColumns );
726 // let the user (via the interaction handler) fill all remaining parameters
727 Reference< XConnection > xConnection;
728 getConnection( xConnection );
730 if ( _rxCompletionHandler.is() )
731 return completeParameters( _rxCompletionHandler, xConnection );
733 return consultParameterListeners( _rClearForNotifies );
737 bool ParameterManager::getConnection( Reference< XConnection >& /* [out] */ _rxConnection )
739 OSL_PRECOND( isAlive(), "ParameterManager::getConnection: not initialized, or already disposed!" );
740 if ( !isAlive() )
741 return false;
743 _rxConnection.clear();
746 Reference< XPropertySet > xProp = m_xComponent;
747 OSL_ENSURE(xProp.is(),"Some already released my component!");
748 if ( xProp.is() )
749 xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ACTIVE_CONNECTION) ) >>= _rxConnection;
751 catch( const Exception& )
753 SAL_WARN( "connectivity.commontools", "ParameterManager::getConnection: could not retrieve the connection of the !" );
755 return _rxConnection.is();
759 void ParameterManager::cacheConnectionInfo()
763 Reference< XConnection > xConnection;
764 getConnection( xConnection );
765 Reference< XDatabaseMetaData > xMeta;
766 if ( xConnection.is() )
767 xMeta = xConnection->getMetaData();
768 if ( xMeta.is() )
770 m_xConnectionMetadata = xMeta;
771 m_sIdentifierQuoteString = xMeta->getIdentifierQuoteString();
772 m_sSpecialCharacters = xMeta->getExtraNameCharacters();
775 catch( const Exception& )
777 SAL_WARN( "connectivity.commontools", "ParameterManager::cacheConnectionInfo: caught an exception!" );
782 bool ParameterManager::getColumns( Reference< XNameAccess >& /* [out] */ _rxColumns, bool _bFromComposer )
784 _rxColumns.clear();
786 Reference< XColumnsSupplier > xColumnSupp;
787 if ( _bFromComposer )
788 xColumnSupp.set(m_xComposer, css::uno::UNO_QUERY);
789 else
790 xColumnSupp.set( m_xComponent.get(),UNO_QUERY);
791 if ( xColumnSupp.is() )
792 _rxColumns = xColumnSupp->getColumns();
793 OSL_ENSURE( _rxColumns.is(), "ParameterManager::getColumns: could not retrieve the columns for the detail !" );
795 return _rxColumns.is();
799 bool ParameterManager::getParentColumns( Reference< XNameAccess >& /* [out] */ _out_rxParentColumns, bool _bFromComposer )
801 OSL_PRECOND( isAlive(), "ParameterManager::getParentColumns: not initialized, or already disposed!" );
803 _out_rxParentColumns.clear();
806 // get the parent of the component we're working for
807 Reference< XChild > xAsChild( m_xComponent.get(), UNO_QUERY_THROW );
808 Reference< XPropertySet > xParent( xAsChild->getParent(), UNO_QUERY );
809 if ( !xParent.is() )
810 return false;
812 // the columns supplier: either from a composer, or directly from the
813 Reference< XColumnsSupplier > xParentColSupp;
814 if ( _bFromComposer )
816 // re-create the parent composer all the time. Else, we'd have to bother with
817 // being a listener at its properties, its loaded state, and event the parent-relationship.
818 m_xParentComposer.reset(
819 getCurrentSettingsComposer( xParent, m_xContext ),
820 SharedQueryComposer::TakeOwnership
822 xParentColSupp.set(m_xParentComposer, css::uno::UNO_QUERY);
824 else
825 xParentColSupp.set(xParent, css::uno::UNO_QUERY);
827 // get the columns of the parent
828 if ( xParentColSupp.is() )
829 _out_rxParentColumns = xParentColSupp->getColumns();
831 catch( const Exception& )
833 SAL_WARN( "connectivity.commontools", "ParameterManager::getParentColumns: caught an exception!" );
835 return _out_rxParentColumns.is();
839 void ParameterManager::addParameterListener( const Reference< XDatabaseParameterListener >& _rxListener )
841 if ( _rxListener.is() )
842 m_aParameterListeners.addInterface( _rxListener );
846 void ParameterManager::removeParameterListener( const Reference< XDatabaseParameterListener >& _rxListener )
848 m_aParameterListeners.removeInterface( _rxListener );
852 void ParameterManager::resetParameterValues( )
854 OSL_PRECOND( isAlive(), "ParameterManager::resetParameterValues: not initialized, or already disposed!" );
855 if ( !isAlive() )
856 return;
858 if ( !m_nInnerCount )
859 // no parameters at all
860 return;
864 Reference< XNameAccess > xColumns;
865 if ( !getColumns( xColumns, false ) )
866 // already asserted in getColumns
867 return;
869 Reference< XNameAccess > xParentColumns;
870 if ( !getParentColumns( xParentColumns, false ) )
871 return;
873 // loop through all links pairs
874 const OUString* pMasterFields = m_aMasterFields.getConstArray();
875 const OUString* pDetailFields = m_aDetailFields.getConstArray();
877 Reference< XPropertySet > xMasterField;
878 Reference< XPropertySet > xDetailField;
880 // now really ....
881 const OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength();
882 for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields )
884 if ( !xParentColumns->hasByName( *pMasterFields ) )
886 // if this name is unknown in the parent columns, then we don't have a source
887 // for copying the value to the detail columns
888 SAL_WARN( "connectivity.commontools", "ParameterManager::resetParameterValues: this should have been stripped long before!" );
889 continue;
892 // for all inner parameters which are bound to the name as specified by the
893 // slave element of the link, propagate the value from the master column to this
894 // parameter column
895 ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields );
896 if ( ( aParamInfo == m_aParameterInformation.end() )
897 || ( aParamInfo->second.aInnerIndexes.empty() )
900 SAL_WARN( "connectivity.commontools", "ParameterManager::resetParameterValues: nothing known about this detail field!" );
901 continue;
904 xParentColumns->getByName( *pMasterFields ) >>= xMasterField;
905 if ( !xMasterField.is() )
906 continue;
908 for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin();
909 aPosition != aParamInfo->second.aInnerIndexes.end();
910 ++aPosition
913 Reference< XPropertySet > xInnerParameter;
914 m_xInnerParamColumns->getByIndex( *aPosition ) >>= xInnerParameter;
915 if ( !xInnerParameter.is() )
916 continue;
918 OUString sParamColumnRealName;
919 xInnerParameter->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME) ) >>= sParamColumnRealName;
920 if ( xColumns->hasByName( sParamColumnRealName ) )
921 { // our own columns have a column which's name equals the real name of the param column
922 // -> transfer the value property
923 xColumns->getByName( sParamColumnRealName ) >>= xDetailField;
924 if ( xDetailField.is() )
925 xDetailField->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ) );
930 catch( const Exception& )
932 SAL_WARN( "connectivity.commontools", "ParameterManager::resetParameterValues: caught an exception!" );
938 void ParameterManager::externalParameterVisited( sal_Int32 _nIndex )
940 if ( m_aParametersVisited.size() < (size_t)_nIndex )
942 m_aParametersVisited.reserve( _nIndex );
943 for ( sal_Int32 i = m_aParametersVisited.size(); i < _nIndex; ++i )
944 m_aParametersVisited.push_back( false );
946 m_aParametersVisited[ _nIndex - 1 ] = true;
949 #define VISIT_PARAMETER( method ) \
950 ::osl::MutexGuard aGuard( m_rMutex ); \
951 OSL_ENSURE( m_xInnerParamUpdate.is(), "ParameterManager::XParameters::setXXX: no XParameters access to the RowSet!" ); \
952 if ( !m_xInnerParamUpdate.is() ) \
953 return; \
954 m_xInnerParamUpdate->method; \
955 externalParameterVisited( _nIndex ) \
958 void ParameterManager::setNull( sal_Int32 _nIndex, sal_Int32 sqlType )
960 VISIT_PARAMETER( setNull( _nIndex, sqlType ) );
964 void ParameterManager::setObjectNull( sal_Int32 _nIndex, sal_Int32 sqlType, const OUString& typeName )
966 VISIT_PARAMETER( setObjectNull( _nIndex, sqlType, typeName ) );
970 void ParameterManager::setBoolean( sal_Int32 _nIndex, bool x )
972 VISIT_PARAMETER( setBoolean( _nIndex, x ) );
976 void ParameterManager::setByte( sal_Int32 _nIndex, sal_Int8 x )
978 VISIT_PARAMETER( setByte( _nIndex, x ) );
982 void ParameterManager::setShort( sal_Int32 _nIndex, sal_Int16 x )
984 VISIT_PARAMETER( setShort( _nIndex, x ) );
988 void ParameterManager::setInt( sal_Int32 _nIndex, sal_Int32 x )
990 VISIT_PARAMETER( setInt( _nIndex, x ) );
994 void ParameterManager::setLong( sal_Int32 _nIndex, sal_Int64 x )
996 VISIT_PARAMETER( setLong( _nIndex, x ) );
1000 void ParameterManager::setFloat( sal_Int32 _nIndex, float x )
1002 VISIT_PARAMETER( setFloat( _nIndex, x ) );
1006 void ParameterManager::setDouble( sal_Int32 _nIndex, double x )
1008 VISIT_PARAMETER( setDouble( _nIndex, x ) );
1012 void ParameterManager::setString( sal_Int32 _nIndex, const OUString& x )
1014 VISIT_PARAMETER( setString( _nIndex, x ) );
1018 void ParameterManager::setBytes( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x )
1020 VISIT_PARAMETER( setBytes( _nIndex, x ) );
1024 void ParameterManager::setDate( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x )
1026 VISIT_PARAMETER( setDate( _nIndex, x ) );
1030 void ParameterManager::setTime( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x )
1032 VISIT_PARAMETER( setTime( _nIndex, x ) );
1036 void ParameterManager::setTimestamp( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x )
1038 VISIT_PARAMETER( setTimestamp( _nIndex, x ) );
1042 void ParameterManager::setBinaryStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length )
1044 VISIT_PARAMETER( setBinaryStream( _nIndex, x, length ) );
1048 void ParameterManager::setCharacterStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length )
1050 VISIT_PARAMETER( setCharacterStream( _nIndex, x, length ) );
1054 void ParameterManager::setObject( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x )
1056 VISIT_PARAMETER( setObject( _nIndex, x ) );
1060 void ParameterManager::setObjectWithInfo( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale )
1062 VISIT_PARAMETER( setObjectWithInfo( _nIndex, x, targetSqlType, scale ) );
1066 void ParameterManager::setRef( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x )
1068 VISIT_PARAMETER( setRef( _nIndex, x ) );
1072 void ParameterManager::setBlob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x )
1074 VISIT_PARAMETER( setBlob( _nIndex, x ) );
1078 void ParameterManager::setClob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x )
1080 VISIT_PARAMETER( setClob( _nIndex, x ) );
1084 void ParameterManager::setArray( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x )
1086 VISIT_PARAMETER( setArray( _nIndex, x ) );
1090 void ParameterManager::clearParameters( )
1092 if ( m_xInnerParamUpdate.is() )
1093 m_xInnerParamUpdate->clearParameters( );
1096 void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw( RuntimeException, std::exception )
1098 m_aValues = _rValues;
1102 } // namespace frm
1105 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */