blob: 46e100146ab6e4533fdf369cf7a52d681a5904f4 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef CONNECTIVITY_PARAMETERS_HXX
#define CONNECTIVITY_PARAMETERS_HXX
#include <map>
#include <vector>
/** === begin UNO includes === **/
#include <com/sun/star/uno/XAggregation.hpp>
#include <com/sun/star/form/XDatabaseParameterListener.hpp>
#include <com/sun/star/sdbc/XConnection.hpp>
#include <com/sun/star/task/XInteractionHandler.hpp>
#include <com/sun/star/sdbc/XParameters.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
/** === end UNO includes === **/
#include "connectivity/dbtoolsdllapi.hxx"
#include "connectivity/paramwrapper.hxx"
#include <unotools/sharedunocomponent.hxx>
#include <comphelper/implementationreference.hxx>
#include <cppuhelper/interfacecontainer.hxx>
//........................................................................
namespace dbtools
{
//........................................................................
typedef ::utl::SharedUNOComponent< ::com::sun::star::sdb::XSingleSelectQueryComposer, ::utl::DisposableComponent >
SharedQueryComposer;
//====================================================================
//= ParameterManager
//====================================================================
class FilterManager;
class OOO_DLLPUBLIC_DBTOOLS ParameterManager
{
public:
/// classifies the origin of the data to fill a parameter
enum ParameterClassification
{
/** parameters which are filled from the master-detail relationship, where the detail
name is an explicit parameter name
*/
eLinkedByParamName,
/** parameters which are filled from the master-detail relationship, where the detail
name is a column name, so an implicit parameter had to be generated for it
*/
eLinkedByColumnName,
/** parameters which are filled externally (i.e. by XParamaters::setXXX, or by the parameter listeners)
*/
eFilledExternally
};
/** meta data about an inner parameter
*/
private:
struct ParameterMetaData
{
/// the type of the parameter
ParameterClassification eType;
/// the column object for this parameter, as returned by the query composer
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
xComposerColumn;
/// the indicies of inner parameters which need to be filled when this concrete parameter is set
::std::vector< sal_Int32 > aInnerIndexes;
/// default ctor
ParameterMetaData()
:eType( eFilledExternally )
{
}
/// ctor with composer column
ParameterMetaData( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxColumn )
:eType ( eFilledExternally )
,xComposerColumn ( _rxColumn )
{
}
};
typedef ::std::map< ::rtl::OUString, ParameterMetaData > ParameterInformation;
private:
::osl::Mutex& m_rMutex;
::cppu::OInterfaceContainerHelper m_aParameterListeners;
::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >
m_xORB;
::com::sun::star::uno::WeakReference< ::com::sun::star::beans::XPropertySet >
m_xComponent; // the database component whose parameters we're handling
::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation >
m_xAggregatedRowSet; // the aggregated row set - necessary for unwrapped access to some interfaces
::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XParameters >
m_xInnerParamUpdate; // write access to the inner parameters
SharedQueryComposer m_xComposer; // query composer wrapping the statement which the *aggregate* is based on
SharedQueryComposer m_xParentComposer; // query composer wrapping the statement of our parent database component
::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >
m_xInnerParamColumns; // index access to the parameter columns, as got from the query composer
::dbtools::param::ParametersContainerRef
m_pOuterParameters; // the container of parameters which still need to be filled in by
// external instances
sal_Int32 m_nInnerCount; // overall number of parameters as required by the database component's aggregate
ParameterInformation m_aParameterInformation;
::com::sun::star::uno::Sequence< ::rtl::OUString > m_aMasterFields;
::com::sun::star::uno::Sequence< ::rtl::OUString > m_aDetailFields;
::rtl::OUString m_sIdentifierQuoteString;
::rtl::OUString m_sSpecialCharacters;
::std::vector< bool > m_aParametersVisited;
bool m_bUpToDate;
public:
/** ctor
*/
explicit ParameterManager(
::osl::Mutex& _rMutex,
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB
);
/// late ctor
void initialize(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxComponent,
const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation >& _rxComponentAggregate
);
/// makes the object forgetting the references to the database component
void dispose( );
/// clears the instance data
void clearAllParameterInformation();
/// checks whether the parameter information are up-to-date
inline bool isUpToDate() const { return m_bUpToDate; }
/** updates all parameter information represented by the instance
*/
void updateParameterInfo( FilterManager& _rFilterManager );
/** fills parameter values, as extensive as possible
<p>In particular, all values which can be filled from the master-detail relationship of
between our database component and it's parent are filled in.</p>
@param _rxCompletionHandler
an interaction handler which should be used to fill all parameters which
cannot be filled by other means. May be <NULL/>
@param _rClearForNotifies
the mutex guard to be (temporarily) cleared for notifications
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
@return
<TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
*/
bool fillParameterValues(
const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler,
::osl::ResettableMutexGuard& _rClearForNotifies
);
/** sets all parameter values to null (via <member>XParameters::setNull</member>)
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
*/
void setAllParametersNull() SAL_THROW( ( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException ) );
/** resets all detail columns which are, via a parameter, linked to a master column, to
the value of this master column.
For instance, if the database component is bound to a statement <code>SELECT * from invoice where inv_id = :cid</code>,
and there is <em>one</em> master-detail link from
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
*/
void resetParameterValues() SAL_THROW(());
/** tells the object that it's database component is being disposed
The object then fires the <member>XEventListener::disposing</member> notification to
the parameter listeners
*/
void disposing( const ::com::sun::star::lang::EventObject& _rDisposingEvent );
/** adds the given listener to the list of parameter listeners
*/
void addParameterListener(
const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener >& _rxListener
);
/** removes the given listener from the list of parameter listeners
*/
void removeParameterListener(
const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener >& _rxListener
);
// XParameters equivalents
void setNull ( sal_Int32 _nIndex, sal_Int32 sqlType);
void setObjectNull ( sal_Int32 _nIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName);
void setBoolean ( sal_Int32 _nIndex, sal_Bool x);
void setByte ( sal_Int32 _nIndex, sal_Int8 x);
void setShort ( sal_Int32 _nIndex, sal_Int16 x);
void setInt ( sal_Int32 _nIndex, sal_Int32 x);
void setLong ( sal_Int32 _nIndex, sal_Int64 x);
void setFloat ( sal_Int32 _nIndex, float x);
void setDouble ( sal_Int32 _nIndex, double x);
void setString ( sal_Int32 _nIndex, const ::rtl::OUString& x);
void setBytes ( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x);
void setDate ( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x);
void setTime ( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x);
void setTimestamp ( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x);
void setBinaryStream ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length);
void setCharacterStream ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length);
void setObject ( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x);
void setObjectWithInfo ( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale);
void setRef ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x);
void setBlob ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x);
void setClob ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x);
void setArray ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x);
void clearParameters();
private:
/// checkes whether the object is already initialized, and not yet disposed
inline bool isAlive() const { return m_xComponent.get().is() && m_xInnerParamUpdate.is(); }
/** creates a filter expression from a master-detail link where the detail denotes a column name
*/
::rtl::OUString
createFilterConditionFromColumnLink(
const ::rtl::OUString& /* [in] */ _rMasterColumn,
const ::rtl::OUString& /* [in] */ _rDetailColumn,
::rtl::OUString& /* [out] */ _rNewParamName
);
/** initializes our query composer, and the collection of inner parameter columns
@param _rxComponent
the database component to initialize from. Must not be <NULL/>
@return
<TRUE/> if and only if the initialization was successfull
@postcond
if and only if <TRUE/> is returned, then <member>m_xInnerParamColumns</member> contains the collection of
inner parameters
*/
bool initializeComposerByComponent(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxComponent
);
/** collects initial meta information about inner paramaters (i.e. it initially fills
<member>m_aParameterInformation</member>).
@param _bSecondRun
if <TRUE/>, this is the second run, because we ourself previously extended the filter of
the RowSet
@precond
<member>m_xInnerParamColumns</member> is not <NULL/>
*/
void collectInnerParameters( bool _bSecondRun );
/** analyzes the master-detail links for our database component, and initializes m_aMasterFields and m_aDetailFields
@param _rFilterManager
the filter manager of the database component
@param _rColumnsInLinkDetails
will be set to <TRUE/> if and only if there were link pairs where the detail field denoted
a column name of our database component
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
*/
void analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails );
/** classifies the link pairs
@param _rxParentColumns
the columns of the parent database component
@param _rxColumns
the columns of our own database component
@param _out_rAdditionalFilterComponents
the additional filter components which are required for master-detail relationships where
the detail part denotes a column name. In such a case, an additional filter needs to be created,
containing a new parameter.
@precond
<member>m_aMasterFields</member> and <member>m_aDetailFields</member> have the same length
*/
void classifyLinks(
const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxParentColumns,
const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxColumns,
::std::vector< ::rtl::OUString >& _out_rAdditionalFilterComponents
) SAL_THROW(( ::com::sun::star::uno::Exception ));
/** finalizes our <member>m_pOuterParameters</member> so that it can be used for
external parameter listeners
@precond
<member>m_pOuterParameters</member> is <NULL/>
@precond
<member>m_xInnerParamUpdate</member> is not <NULL/>
*/
void createOuterParameters();
/** fills in the parameters values which result from the master-detail relationship
between the database component and it's parent
@param _rxParentColumns
the columns of the parameter database component. Must not be <NULL/>
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
*/
void fillLinkedParameters(
const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxParentColumns
);
/** completes all missing parameters via an interaction handler
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
@return
<TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
*/
bool completeParameters(
const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler,
const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > _rxConnection
);
/** asks the parameter listeners to fill in final values
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
@return
<TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
*/
bool consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies );
/** mark an externally filled parameter asvisited
*/
void externalParameterVisited( sal_Int32 _nIndex );
private:
/** retrieves the columns of the parent database component
@precond
the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
@return
<TRUE/> if and only if the columns could be successfully retrieved
*/
bool getParentColumns(
::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& /* [out] */ _out_rxParentColumns,
bool _bFromComposer
);
/** retrieves the columns of our database component
@param _bFromComposer
if <TRUE/>, the columns are obtained from the composer, else from the living database component itself
@return
<TRUE/> if and only if the columns could be successfully retrieved
*/
bool getColumns(
::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& /* [out] */ _rxColumns,
bool _bFromComposer
) SAL_THROW(( ::com::sun::star::uno::Exception ));
/** retrieves the active connection of the database component
*/
bool getConnection(
::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& /* [out] */ _rxConnection
);
/** caches some info about the connection of our database component
*/
void cacheConnectionInfo() SAL_THROW(( ));
private:
ParameterManager(); // never implemented
ParameterManager( const ParameterManager& ); // never implemented
ParameterManager& operator=( const ParameterManager& ); // never implemented
};
//........................................................................
} // namespacefrm
//........................................................................
#endif // CONNECTIVITY_PARAMETERS_HXX