1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef CONNECTIVITY_PARAMETERS_HXX
24 #define CONNECTIVITY_PARAMETERS_HXX
25 
26 #include <map>
27 #include <vector>
28 
29 /** === begin UNO includes === **/
30 #include <com/sun/star/uno/XAggregation.hpp>
31 #include <com/sun/star/form/XDatabaseParameterListener.hpp>
32 #include <com/sun/star/sdbc/XConnection.hpp>
33 #include <com/sun/star/task/XInteractionHandler.hpp>
34 #include <com/sun/star/sdbc/XParameters.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/container/XIndexAccess.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
39 /** === end UNO includes === **/
40 
41 #include "connectivity/dbtoolsdllapi.hxx"
42 #include "connectivity/paramwrapper.hxx"
43 #include <unotools/sharedunocomponent.hxx>
44 #include <comphelper/implementationreference.hxx>
45 #include <cppuhelper/interfacecontainer.hxx>
46 
47 //........................................................................
48 namespace dbtools
49 {
50 //........................................................................
51 
52     typedef ::utl::SharedUNOComponent< ::com::sun::star::sdb::XSingleSelectQueryComposer, ::utl::DisposableComponent >
53             SharedQueryComposer;
54 
55     //====================================================================
56 	//= ParameterManager
57 	//====================================================================
58     class FilterManager;
59     class OOO_DLLPUBLIC_DBTOOLS ParameterManager
60 	{
61     public:
62         /// classifies the origin of the data to fill a parameter
63         enum ParameterClassification
64         {
65             /** parameters which are filled from the master-detail relationship, where the detail
66                 name is an explicit parameter name
67             */
68             eLinkedByParamName,
69             /** parameters which are filled from the master-detail relationship, where the detail
70                 name is a column name, so an implicit parameter had to be generated for it
71             */
72             eLinkedByColumnName,
73             /** parameters which are filled externally (i.e. by XParamaters::setXXX, or by the parameter listeners)
74             */
75             eFilledExternally
76         };
77         /** meta data about an inner parameter
78         */
79 	private:
80         struct ParameterMetaData
81         {
82             /// the type of the parameter
83             ParameterClassification     eType;
84             /// the column object for this parameter, as returned by the query composer
85             ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
86                                         xComposerColumn;
87             /// the indicies of inner parameters which need to be filled when this concrete parameter is set
88             ::std::vector< sal_Int32 >  aInnerIndexes;
89 
90             /// default ctor
ParameterMetaDatadbtools::ParameterManager::ParameterMetaData91             ParameterMetaData()
92                 :eType( eFilledExternally )
93             {
94             }
95 
96             /// ctor with composer column
ParameterMetaDatadbtools::ParameterManager::ParameterMetaData97             ParameterMetaData( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxColumn )
98                 :eType           ( eFilledExternally )
99                 ,xComposerColumn ( _rxColumn         )
100             {
101             }
102         };
103 
104         typedef ::std::map< ::rtl::OUString, ParameterMetaData >    ParameterInformation;
105 
106     private:
107         ::osl::Mutex&                       m_rMutex;
108 	    ::cppu::OInterfaceContainerHelper	m_aParameterListeners;
109 
110         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >
111                                             m_xORB;
112 
113         ::com::sun::star::uno::WeakReference< ::com::sun::star::beans::XPropertySet >
114                                             m_xComponent;                // the database component whose parameters we're handling
115         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation >
116                                             m_xAggregatedRowSet;    // the aggregated row set - necessary for unwrapped access to some interfaces
117         ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XParameters >
118                                             m_xInnerParamUpdate;    // write access to the inner parameters
119         SharedQueryComposer                 m_xComposer;            // query composer wrapping the statement which the *aggregate* is based on
120         SharedQueryComposer                 m_xParentComposer;      // query composer wrapping the statement of our parent database component
121         ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >
122                                             m_xInnerParamColumns;   // index access to the parameter columns, as got from the query composer
123 
124         ::dbtools::param::ParametersContainerRef
125                                             m_pOuterParameters;     // the container of parameters which still need to be filled in by
126                                                                     // external instances
127         sal_Int32                           m_nInnerCount;          // overall number of parameters as required by the database component's aggregate
128 
129         ParameterInformation                m_aParameterInformation;
130 
131         ::com::sun::star::uno::Sequence< ::rtl::OUString >  m_aMasterFields;
132         ::com::sun::star::uno::Sequence< ::rtl::OUString >  m_aDetailFields;
133 
134         ::rtl::OUString                     m_sIdentifierQuoteString;
135         ::rtl::OUString                     m_sSpecialCharacters;
136 
137         ::std::vector< bool >               m_aParametersVisited;
138 
139         bool                                m_bUpToDate;
140 
141     public:
142         /** ctor
143         */
144         explicit ParameterManager(
145             ::osl::Mutex& _rMutex,
146             const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB
147         );
148 
149         /// late ctor
150         void    initialize(
151                     const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxComponent,
152                     const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation >& _rxComponentAggregate
153                 );
154 
155         /// makes the object forgetting the references to the database component
156         void    dispose( );
157 
158         /// clears the instance data
159                 void    clearAllParameterInformation();
160 
161         /// checks whether the parameter information are up-to-date
isUpToDate() const162         inline  bool    isUpToDate() const { return m_bUpToDate; }
163 
164         /** updates all parameter information represented by the instance
165         */
166         void    updateParameterInfo( FilterManager& _rFilterManager );
167 
168         /** fills parameter values, as extensive as possible
169 
170             <p>In particular, all values which can be filled from the master-detail relationship of
171             between our database component and it's parent are filled in.</p>
172 
173             @param _rxCompletionHandler
174                 an interaction handler which should be used to fill all parameters which
175                 cannot be filled by other means. May be <NULL/>
176             @param _rClearForNotifies
177                 the mutex guard to be (temporarily) cleared for notifications
178 
179             @precond
180                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
181 
182             @return
183                 <TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
184         */
185         bool    fillParameterValues(
186                     const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler,
187                     ::osl::ResettableMutexGuard& _rClearForNotifies
188                 );
189 
190         /** sets all parameter values to null (via <member>XParameters::setNull</member>)
191 
192             @precond
193                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
194         */
195         void    setAllParametersNull() SAL_THROW( ( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException ) );
196 
197         /** resets all detail columns which are, via a parameter, linked to a master column, to
198             the value of this master column.
199 
200             For instance, if the database component is bound to a statement <code>SELECT * from invoice where inv_id = :cid</code>,
201             and there is <em>one</em> master-detail link from
202 
203             @precond
204                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
205         */
206         void    resetParameterValues() SAL_THROW(());
207 
208         /** tells the object that it's database component is being disposed
209 
210             The object then fires the <member>XEventListener::disposing</member> notification to
211             the parameter listeners
212         */
213         void    disposing( const ::com::sun::star::lang::EventObject& _rDisposingEvent );
214 
215         /** adds the given listener to the list of parameter listeners
216         */
217         void    addParameterListener(
218                     const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener >& _rxListener
219                 );
220 
221         /** removes the given listener from the list of parameter listeners
222         */
223         void    removeParameterListener(
224                     const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener >& _rxListener
225                 );
226 
227         // XParameters equivalents
228         void setNull            ( sal_Int32 _nIndex, sal_Int32 sqlType);
229         void setObjectNull      ( sal_Int32 _nIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName);
230         void setBoolean         ( sal_Int32 _nIndex, sal_Bool x);
231         void setByte            ( sal_Int32 _nIndex, sal_Int8 x);
232         void setShort           ( sal_Int32 _nIndex, sal_Int16 x);
233         void setInt             ( sal_Int32 _nIndex, sal_Int32 x);
234         void setLong            ( sal_Int32 _nIndex, sal_Int64 x);
235         void setFloat           ( sal_Int32 _nIndex, float x);
236         void setDouble          ( sal_Int32 _nIndex, double x);
237         void setString          ( sal_Int32 _nIndex, const ::rtl::OUString& x);
238         void setBytes           ( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x);
239         void setDate            ( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x);
240         void setTime            ( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x);
241         void setTimestamp       ( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x);
242         void setBinaryStream    ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length);
243         void setCharacterStream ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length);
244         void setObject          ( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x);
245         void setObjectWithInfo  ( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale);
246         void setRef             ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x);
247         void setBlob            ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x);
248         void setClob            ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x);
249         void setArray           ( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x);
250         void clearParameters();
251 
252     private:
253         /// checkes whether the object is already initialized, and not yet disposed
isAlive() const254         inline  bool    isAlive() const { return m_xComponent.get().is() && m_xInnerParamUpdate.is(); }
255 
256         /** creates a filter expression from a master-detail link where the detail denotes a column name
257         */
258         ::rtl::OUString
259                 createFilterConditionFromColumnLink(
260                     const ::rtl::OUString& /* [in]  */ _rMasterColumn,
261                     const ::rtl::OUString& /* [in]  */ _rDetailColumn,
262                           ::rtl::OUString& /* [out] */ _rNewParamName
263                 );
264 
265         /** initializes our query composer, and the collection of inner parameter columns
266 
267             @param _rxComponent
268                 the database component to initialize from. Must not be <NULL/>
269             @return
270                 <TRUE/> if and only if the initialization was successfull
271 
272             @postcond
273                 if and only if <TRUE/> is returned, then <member>m_xInnerParamColumns</member> contains the collection of
274                 inner parameters
275         */
276         bool    initializeComposerByComponent(
277                     const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxComponent
278                 );
279 
280         /** collects initial meta information about inner paramaters (i.e. it initially fills
281             <member>m_aParameterInformation</member>).
282 
283             @param _bSecondRun
284                 if <TRUE/>, this is the second run, because we ourself previously extended the filter of
285                 the RowSet
286 
287             @precond
288                 <member>m_xInnerParamColumns</member> is not <NULL/>
289         */
290         void    collectInnerParameters( bool _bSecondRun );
291 
292         /** analyzes the master-detail links for our database component, and initializes m_aMasterFields and m_aDetailFields
293 
294             @param _rFilterManager
295                 the filter manager of the database component
296             @param _rColumnsInLinkDetails
297                 will be set to <TRUE/> if and only if there were link pairs where the detail field denoted
298                 a column name of our database component
299 
300             @precond
301                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
302         */
303         void    analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails );
304 
305         /** classifies the link pairs
306 
307             @param  _rxParentColumns
308                 the columns of the parent database component
309 
310             @param  _rxColumns
311                 the columns of our own database component
312 
313             @param  _out_rAdditionalFilterComponents
314                 the additional filter components which are required for master-detail relationships where
315                 the detail part denotes a column name. In such a case, an additional filter needs to be created,
316                 containing a new parameter.
317 
318             @precond
319                 <member>m_aMasterFields</member> and <member>m_aDetailFields</member> have the same length
320         */
321         void    classifyLinks(
322                     const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxParentColumns,
323                     const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxColumns,
324                     ::std::vector< ::rtl::OUString >& _out_rAdditionalFilterComponents
325                 )   SAL_THROW(( ::com::sun::star::uno::Exception ));
326 
327         /** finalizes our <member>m_pOuterParameters</member> so that it can be used for
328             external parameter listeners
329 
330             @precond
331                 <member>m_pOuterParameters</member> is <NULL/>
332             @precond
333                 <member>m_xInnerParamUpdate</member> is not <NULL/>
334         */
335         void    createOuterParameters();
336 
337         /** fills in the parameters values which result from the master-detail relationship
338             between the database component and it's parent
339 
340             @param _rxParentColumns
341                 the columns of the parameter database component. Must not be <NULL/>
342             @precond
343                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
344         */
345         void    fillLinkedParameters(
346                     const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxParentColumns
347                 );
348 
349         /** completes all missing parameters via an interaction handler
350 
351             @precond
352                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
353 
354             @return
355                 <TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
356         */
357         bool    completeParameters(
358                     const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler,
359                     const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > _rxConnection
360                 );
361 
362         /** asks the parameter listeners to fill in final values
363 
364             @precond
365                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
366 
367             @return
368                 <TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
369         */
370         bool    consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies );
371 
372         /** mark an externally filled parameter asvisited
373         */
374         void    externalParameterVisited( sal_Int32 _nIndex );
375 
376     private:
377         /** retrieves the columns of the parent database component
378 
379             @precond
380                 the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
381             @return
382                 <TRUE/> if and only if the columns could be successfully retrieved
383         */
384         bool    getParentColumns(
385                     ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& /* [out] */ _out_rxParentColumns,
386                     bool _bFromComposer
387                 );
388 
389         /** retrieves the columns of our database component
390 
391             @param _bFromComposer
392                 if <TRUE/>, the columns are obtained from the composer, else from the living database component itself
393             @return
394                 <TRUE/> if and only if the columns could be successfully retrieved
395         */
396         bool    getColumns(
397                     ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& /* [out] */ _rxColumns,
398                     bool _bFromComposer
399                 ) SAL_THROW(( ::com::sun::star::uno::Exception ));
400 
401         /** retrieves the active connection of the database component
402         */
403         bool    getConnection(
404                     ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& /* [out] */ _rxConnection
405                 );
406 
407         /** caches some info about the connection of our database component
408         */
409         void    cacheConnectionInfo() SAL_THROW(( ));
410 
411     private:
412         ParameterManager();                                      // never implemented
413         ParameterManager( const ParameterManager& );              // never implemented
414         ParameterManager& operator=( const ParameterManager& );   // never implemented
415     };
416 
417 //........................................................................
418 } // namespacefrm
419 //........................................................................
420 
421 #endif // CONNECTIVITY_PARAMETERS_HXX
422 
423