diff options
Diffstat (limited to 'include/connectivity/parameters.hxx')
-rw-r--r-- | include/connectivity/parameters.hxx | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/include/connectivity/parameters.hxx b/include/connectivity/parameters.hxx new file mode 100644 index 0000000000..8d526c983a --- /dev/null +++ b/include/connectivity/parameters.hxx @@ -0,0 +1,416 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#ifndef INCLUDED_CONNECTIVITY_PARAMETERS_HXX +#define INCLUDED_CONNECTIVITY_PARAMETERS_HXX + +#include <map> +#include <utility> +#include <vector> + +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> + +#include <connectivity/dbtoolsdllapi.hxx> +#include <connectivity/paramwrapper.hxx> +#include <unotools/sharedunocomponent.hxx> +#include <comphelper/interfacecontainer3.hxx> + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::container { class XIndexAccess; } +namespace com::sun::star::form { class XDatabaseParameterListener; } +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::sdbc { class XArray; } +namespace com::sun::star::sdbc { class XBlob; } +namespace com::sun::star::sdbc { class XClob; } +namespace com::sun::star::sdbc { class XConnection; } +namespace com::sun::star::sdbc { class XDatabaseMetaData; } +namespace com::sun::star::sdbc { class XParameters; } +namespace com::sun::star::sdbc { class XRef; } +namespace com::sun::star::task { class XInteractionHandler; } +namespace com::sun::star::uno { class XAggregation; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace dbtools +{ + + + typedef ::utl::SharedUNOComponent< css::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 class ParameterClassification + { + /** parameters which are filled from the master-detail relationship, where the detail + name is an explicit parameter name + */ + LinkedByParamName, + /** 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 + */ + LinkedByColumnName, + /** parameters which are filled externally (i.e. by XParameters::setXXX, or by the parameter listeners) + */ + FilledExternally + }; + /** 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 + css::uno::Reference< css::beans::XPropertySet > + xComposerColumn; + /// the indices of inner parameters which need to be filled when this concrete parameter is set + ::std::vector< sal_Int32 > aInnerIndexes; + + /// ctor with composer column + ParameterMetaData( css::uno::Reference< css::beans::XPropertySet > _xColumn ) + :eType ( ParameterClassification::FilledExternally ) + ,xComposerColumn (std::move( _xColumn )) + { + } + }; + + typedef ::std::map< OUString, ParameterMetaData > ParameterInformation; + + private: + ::osl::Mutex& m_rMutex; + ::comphelper::OInterfaceContainerHelper3<css::form::XDatabaseParameterListener> m_aParameterListeners; + + css::uno::Reference< css::uno::XComponentContext > + m_xContext; + + css::uno::WeakReference< css::beans::XPropertySet > + m_xComponent; // the database component whose parameters we're handling + css::uno::Reference< css::uno::XAggregation > + m_xAggregatedRowSet; // the aggregated row set - necessary for unwrapped access to some interfaces + css::uno::Reference< css::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 + css::uno::Reference< css::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; + + std::vector< OUString > m_aMasterFields; + std::vector< OUString > m_aDetailFields; + + OUString m_sIdentifierQuoteString; + OUString m_sSpecialCharacters; + css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xConnectionMetadata; + + ::std::vector< bool > m_aParametersVisited; + + bool m_bUpToDate; + + public: + /** ctor + */ + explicit ParameterManager( + ::osl::Mutex& _rMutex, + const css::uno::Reference< css::uno::XComponentContext >& _rxContext + ); + + /// late ctor + void initialize( + const css::uno::Reference< css::beans::XPropertySet >& _rxComponent, + const css::uno::Reference< css::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 is up-to-date + 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 its 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 css::uno::Reference< css::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(); + + /** 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(); + + /** adds the given listener to the list of parameter listeners + */ + void addParameterListener( + const css::uno::Reference< css::form::XDatabaseParameterListener >& _rxListener + ); + + /** removes the given listener from the list of parameter listeners + */ + void removeParameterListener( + const css::uno::Reference< css::form::XDatabaseParameterListener >& _rxListener + ); + + // XParameters equivalents + void setNull ( sal_Int32 _nIndex, sal_Int32 sqlType); + void setObjectNull ( sal_Int32 _nIndex, sal_Int32 sqlType, const OUString& typeName); + void setBoolean ( sal_Int32 _nIndex, 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 OUString& x); + void setBytes ( sal_Int32 _nIndex, const css::uno::Sequence< sal_Int8 >& x); + void setDate ( sal_Int32 _nIndex, const css::util::Date& x); + void setTime ( sal_Int32 _nIndex, const css::util::Time& x); + void setTimestamp ( sal_Int32 _nIndex, const css::util::DateTime& x); + void setBinaryStream ( sal_Int32 _nIndex, const css::uno::Reference< css::io::XInputStream>& x, sal_Int32 length); + void setCharacterStream ( sal_Int32 _nIndex, const css::uno::Reference< css::io::XInputStream>& x, sal_Int32 length); + void setObject ( sal_Int32 _nIndex, const css::uno::Any& x); + void setObjectWithInfo ( sal_Int32 _nIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale); + void setRef ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XRef>& x); + void setBlob ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XBlob>& x); + void setClob ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XClob>& x); + void setArray ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XArray>& x); + void clearParameters(); + + private: + /// checks whether the object is already initialized, and not yet disposed + 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 + */ + OUString + createFilterConditionFromColumnLink( + const OUString& /* [in] */ _rMasterColumn, + const css::uno::Reference< css::beans::XPropertySet >& /* [in] */ xDetailColumn, + 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 successful + + @postcond + if and only if <TRUE/> is returned, then <member>m_xInnerParamColumns</member> contains the collection of + inner parameters + */ + bool initializeComposerByComponent( + const css::uno::Reference< css::beans::XPropertySet >& _rxComponent + ); + + /** collects initial meta information about inner parameters (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. + + @param _out_rAdditionalHavingComponents + the additional having clause 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 css::uno::Reference< css::container::XNameAccess >& _rxParentColumns, + const css::uno::Reference< css::container::XNameAccess >& _rxColumns, + ::std::vector< OUString >& _out_rAdditionalFilterComponents, + ::std::vector< OUString >& _out_rAdditionalHavingComponents + ); + + /** 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 its 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 css::uno::Reference< css::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 css::uno::Reference< css::task::XInteractionHandler >& _rxCompletionHandler, + const css::uno::Reference< css::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 as visited + */ + 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( + css::uno::Reference< css::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( + css::uno::Reference< css::container::XNameAccess >& /* [out] */ _rxColumns, + bool _bFromComposer + ); + + /** retrieves the active connection of the database component + */ + void getConnection( + css::uno::Reference< css::sdbc::XConnection >& /* [out] */ _rxConnection + ); + + /** caches some info about the connection of our database component + */ + void cacheConnectionInfo(); + + private: + ParameterManager( const ParameterManager& ) = delete; + ParameterManager& operator=( const ParameterManager& ) = delete; + }; + + +} // namespacefrm + + +#endif // INCLUDED_CONNECTIVITY_PARAMETERS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |