| /************************************************************** |
| * |
| * 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 |
| |