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