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 INCLUDED_SW_INC_DBMGR_HXX
20 #define INCLUDED_SW_INC_DBMGR_HXX
21 
22 #include <rtl/ustring.hxx>
23 #include <tools/solar.h>
24 #include <i18nlangtag/lang.h>
25 #include <com/sun/star/util/Date.hpp>
26 #include "swdllapi.h"
27 #include "swdbdata.hxx"
28 #include <com/sun/star/uno/Reference.h>
29 #include <com/sun/star/uno/Sequence.hxx>
30 #include <com/sun/star/lang/Locale.hpp>
31 #include <com/sun/star/beans/PropertyValue.hpp>
32 
33 #include <memory>
34 #include <vector>
35 
36 namespace com{namespace sun{namespace star{
37     namespace sdbc{
38         class XConnection;
39         class XStatement;
40         class XDataSource;
41         class XResultSet;
42     }
43     namespace beans{
44 
45         class XPropertySet;
46     }
47     namespace sdbcx{
48         class XColumnsSupplier;
49     }
50     namespace util{
51         class XNumberFormatter;
52     }
53     namespace mail{
54         class XSmtpService;
55     }
56     namespace embed { class XStorage; }
57     namespace frame { class XStorable; }
58 }}}
59 namespace svx {
60     class ODataAccessDescriptor;
61 }
62 
63 struct SwDBFormatData
64 {
65     css::util::Date aNullDate;
66     css::uno::Reference< css::util::XNumberFormatter> xFormatter;
67     css::lang::Locale aLocale;
68 };
69 
70 namespace weld {
71     class ComboBox;
72     class Window;
73 }
74 
75 class SwView;
76 class SwWrtShell;
77 class ListBox;
78 class SvNumberFormatter;
79 class SwXMailMerge;
80 class SwMailMergeConfigItem;
81 class SwCalc;
82 class INetURLObject;
83 class SwDocShell;
84 
85 enum DBManagerOptions
86 {
87     DBMGR_MERGE,             ///< Data records in fields.
88     DBMGR_MERGE_PRINTER,     ///< Print mail merge.
89     DBMGR_MERGE_EMAIL,       ///< Send mail merge as email.
90     DBMGR_MERGE_FILE,        ///< Save mail merge as files.
91     DBMGR_MERGE_SHELL        ///< Create merge doc and keep the doc shell.
92 };
93 
94 // Administration of (new) logical databases.
95 enum class SwDBSelect
96 {
97     UNKNOWN, TABLE, QUERY
98 };
99 
100 struct SwDSParam : public SwDBData
101 {
102     css::util::Date  aNullDate;
103 
104     css::uno::Reference<css::util::XNumberFormatter>    xFormatter;
105     css::uno::Reference< css::sdbc::XConnection>       xConnection;
106     css::uno::Reference< css::sdbc::XStatement>        xStatement;
107     css::uno::Reference< css::sdbc::XResultSet>        xResultSet;
108     css::uno::Sequence<  css::uno::Any >               aSelection;
109     bool bScrollable;
110     bool bEndOfDB;
111     long nSelectionIndex;
112 
SwDSParamSwDSParam113     SwDSParam(const SwDBData& rData) :
114         SwDBData(rData),
115         bScrollable(false),
116         bEndOfDB(false),
117         nSelectionIndex(0)
118         {}
119 
SwDSParamSwDSParam120     SwDSParam(const SwDBData& rData,
121         const css::uno::Reference< css::sdbc::XResultSet>&    xResSet,
122         const css::uno::Sequence<  css::uno::Any >&   rSelection) :
123         SwDBData(rData),
124         xResultSet(xResSet),
125         aSelection(rSelection),
126         bScrollable(true),
127         bEndOfDB(false),
128         nSelectionIndex(0)
129         {}
130 
HasValidRecordSwDSParam131     bool HasValidRecord() const
132         { return( !bEndOfDB && xResultSet.is() ); }
133 };
134 
135 typedef std::vector<std::unique_ptr<SwDSParam>> SwDSParams_t;
136 
137 struct SwMergeDescriptor
138 {
139     const DBManagerOptions                              nMergeType;
140     SwWrtShell&                                         rSh;
141     const svx::ODataAccessDescriptor&                   rDescriptor;
142 
143     /**
144      * Create a single or multiple results
145      *
146      * This currently just affects FILE, as EMAIL is always
147      * multiple and SHELL and PRINTER are always single.
148      */
149     bool                                                bCreateSingleFile;
150 
151     /**
152      * @defgroup save Export filter settings
153      * @addtogroup save
154      * @{ */
155     OUString                                            sSaveToFilter;
156     OUString                                            sSaveToFilterOptions;
157     css::uno::Sequence< css::beans::PropertyValue >     aSaveToFilterData;
158     /** @} */
159 
160     /**
161      * @defgroup file Mail merge as File settings
162      * @addtogroup file
163      * @{ */
164 
165     /**
166      * Basename incl. the path for the generated files.
167      *
168      * The final filename will be created by concatenating a number to prevent
169      * overwriting an existing file and the extension based on the filter
170      * settings.
171      */
172     OUString                                            sPrefix;
173     /**
174      * Use the sPrefix as the target filename also overwriting an existing
175      * target file.
176      *
177      * Just used for the internal mail merge dialogs as mail merge never
178      * overwrites existing files (see SwDBManager::ExecuteFormLetter).
179      */
180     bool                                                bPrefixIsFilename;
181     /** @} */
182 
183     /**
184      * @defgroup email Mail merge as eMail settings
185      * @addtogroup email
186      * @{ */
187     OUString                                            sSubject;
188     OUString                                            sMailBody;
189     OUString                                            sAttachmentName;
190     css::uno::Sequence< OUString >                      aCopiesTo;
191     css::uno::Sequence< OUString >                      aBlindCopiesTo;
192     css::uno::Reference< css::mail::XSmtpService >      xSmtpServer;
193     bool                                                bSendAsHTML;
194     bool                                                bSendAsAttachment;
195     /** @} */
196 
197     /**
198      * @addtogroup file email
199      * @{ */
200 
201     /** DB column to fetch EMail of Filename from
202      */
203     OUString                                            sDBcolumn;
204 
205     /** @} */
206 
207     /**
208      * @defgroup print Mail merge to Printer
209      * @addtogroup print
210      * @{ */
211     css::uno::Sequence<  css::beans::PropertyValue >    aPrintOptions;
212     /** @} */
213 
214     SwMailMergeConfigItem*                              pMailMergeConfigItem;
215 
SwMergeDescriptorSwMergeDescriptor216     SwMergeDescriptor( const DBManagerOptions nType,
217                        SwWrtShell& rShell,
218                        const svx::ODataAccessDescriptor& rDesc ) :
219         nMergeType(nType),
220         rSh(rShell),
221         rDescriptor(rDesc),
222         bCreateSingleFile( false ),
223         bPrefixIsFilename( false ),
224         bSendAsHTML( true ),
225         bSendAsAttachment( false ),
226         pMailMergeConfigItem( nullptr )
227     {
228         if( nType == DBMGR_MERGE_SHELL || nType == DBMGR_MERGE_PRINTER )
229             bCreateSingleFile = true;
230     }
231 };
232 
233 class SwDoc;
234 
235 class SW_DLLPUBLIC SwDBManager
236 {
237     struct SwDBManager_Impl;
238     class ConnectionDisposedListener_Impl;
239     class MailDispatcherListener_Impl;
240 
241     enum class MergeStatus
242     {
243         Ok = 0, Cancel, Error
244     };
245 
246     MergeStatus     m_aMergeStatus;     ///< current / last merge status
247     bool            m_bInitDBFields : 1;
248     bool            m_bInMerge    : 1;    ///< merge process active
249     bool            m_bMergeSilent : 1;   ///< suppress display of dialogs/boxes (used when called over API)
250     SwDSParams_t    m_DataSourceParams;
251     std::unique_ptr<SwDBManager_Impl>  m_pImpl;
252     const SwXMailMerge* m_pMergeEvtSrc;   ///< != 0 if mail merge events are to be send
253     /// Name of the embedded database that's included in the current document.
254     OUString     m_sEmbeddedName;
255 
256     /// Store last registrations to revoke or commit
257     static std::vector<std::pair<SwDocShell*, OUString>> m_aUncommittedRegistrations;
258 
259     /// Not used connections.
260     std::vector<OUString> m_aNotUsedConnections;
261 
262     /// Set connection as used.
263     void SetAsUsed(const OUString& rName);
264 
265     /// The document that owns this manager.
266     SwDoc* m_pDoc;
267 
268     SAL_DLLPRIVATE SwDSParam*          FindDSData(const SwDBData& rData, bool bCreate);
269     SAL_DLLPRIVATE SwDSParam*          FindDSConnection(const OUString& rSource, bool bCreate);
270 
271     /// Insert data record as text into document.
272     SAL_DLLPRIVATE void ImportFromConnection( SwWrtShell* pSh);
273 
274     /// Insert a single data record as text into document.
275     SAL_DLLPRIVATE void ImportDBEntry(SwWrtShell* pSh);
276 
277     /// Run the mail merge for defined modes, except DBMGR_MERGE
278     SAL_DLLPRIVATE bool MergeMailFiles( SwWrtShell* pSh,
279                                         const SwMergeDescriptor& rMergeDescriptor );
280 
281     SAL_DLLPRIVATE bool ToNextMergeRecord();
282     SAL_DLLPRIVATE bool IsValidMergeRecord() const;
283 
284     SwDBManager(SwDBManager const&) = delete;
285     SwDBManager& operator=(SwDBManager const&) = delete;
286 
287 public:
288     SwDBManager(SwDoc* pDoc);
289     ~SwDBManager() COVERITY_NOEXCEPT_FALSE;
290 
291     /// MailMergeEvent source
GetMailMergeEvtSrc() const292     const SwXMailMerge *    GetMailMergeEvtSrc() const  { return m_pMergeEvtSrc; }
SetMailMergeEvtSrc(const SwXMailMerge * pSrc)293     void SetMailMergeEvtSrc( const SwXMailMerge *pSrc ) { m_pMergeEvtSrc = pSrc; }
294 
IsMergeSilent() const295     bool     IsMergeSilent() const           { return m_bMergeSilent; }
SetMergeSilent(bool bVal)296     void     SetMergeSilent( bool bVal )     { m_bMergeSilent = bVal; }
297 
298     /// Merging of data records into fields.
299     bool            Merge( const SwMergeDescriptor& rMergeDesc );
300     void            MergeCancel();
301 
IsMergeOk() const302     bool     IsMergeOk() const     { return MergeStatus::Ok     == m_aMergeStatus; }
IsMergeError() const303     bool     IsMergeError() const  { return MergeStatus::Error  <= m_aMergeStatus; }
304 
305     static std::shared_ptr<SwMailMergeConfigItem> PerformMailMerge(SwView const * pView);
306 
307     /// Initialize data fields that lack name of database.
IsInitDBFields() const308     bool     IsInitDBFields() const  { return m_bInitDBFields; }
SetInitDBFields(bool b)309     void     SetInitDBFields(bool b) { m_bInitDBFields = b;    }
310 
311     /// Fill listbox with all table names of a database.
312     bool            GetTableNames(weld::ComboBox& rBox, const OUString& rDBName);
313 
314     /// Fill listbox with all column names of a database table.
315     void            GetColumnNames(weld::ComboBox& rBox,
316                             const OUString& rDBName, const OUString& rTableName);
317     static void GetColumnNames(weld::ComboBox& rBox,
318                             css::uno::Reference< css::sdbc::XConnection> const & xConnection,
319                             const OUString& rTableName);
320 
321     static sal_uLong GetColumnFormat( css::uno::Reference< css::sdbc::XDataSource> const & xSource,
322                             css::uno::Reference< css::sdbc::XConnection> const & xConnection,
323                             css::uno::Reference< css::beans::XPropertySet> const & xColumn,
324                             SvNumberFormatter* pNFormatr,
325                             LanguageType nLanguage );
326 
327     sal_uLong GetColumnFormat( const OUString& rDBName,
328                             const OUString& rTableName,
329                             const OUString& rColNm,
330                             SvNumberFormatter* pNFormatr,
331                             LanguageType nLanguage );
332     sal_Int32 GetColumnType( const OUString& rDBName,
333                           const OUString& rTableName,
334                           const OUString& rColNm );
335 
IsInMerge() const336     bool     IsInMerge() const   { return m_bInMerge; }
337 
338     void            ExecuteFormLetter(SwWrtShell& rSh,
339                         const css::uno::Sequence< css::beans::PropertyValue>& rProperties);
340 
341     static void     InsertText(SwWrtShell& rSh,
342                         const css::uno::Sequence< css::beans::PropertyValue>& rProperties);
343 
344     /// check if a data source is open
345     bool            IsDataSourceOpen(const OUString& rDataSource,
346                                     const OUString& rTableOrQuery, bool bMergeShell);
347 
348     /// open the source while fields are updated - for the calculator only!
349     bool            OpenDataSource(const OUString& rDataSource, const OUString& rTableOrQuery);
350     sal_uInt32      GetSelectedRecordId(const OUString& rDataSource, const OUString& rTableOrQuery, sal_Int32 nCommandType = -1);
351     bool            GetColumnCnt(const OUString& rSourceName, const OUString& rTableName,
352                             const OUString& rColumnName, sal_uInt32 nAbsRecordId, LanguageType nLanguage,
353                             OUString& rResult, double* pNumber);
354     /** create and store or find an already stored connection to a data source for use
355     in SwFieldMgr and SwDBTreeList */
356     css::uno::Reference< css::sdbc::XConnection> const &
357                     RegisterConnection(OUString const& rSource);
358 
CreateDSData(const SwDBData & rData)359     void            CreateDSData(const SwDBData& rData)
360                         { FindDSData(rData, true); }
GetDSParamArray() const361     const SwDSParams_t& GetDSParamArray() const { return m_DataSourceParams; }
362 
363     /// close all data sources - after fields were updated
364     void            CloseAll(bool bIncludingMerge = true);
365 
366     bool            GetMergeColumnCnt(const OUString& rColumnName, LanguageType nLanguage,
367                                       OUString &rResult, double *pNumber);
368     bool            FillCalcWithMergeData(SvNumberFormatter *pDocFormatter,
369                                           LanguageType nLanguage, SwCalc &aCalc);
370     void            ToNextRecord(const OUString& rDataSource, const OUString& rTableOrQuery);
371 
372     sal_uInt32      GetSelectedRecordId();
373     bool            ToRecordId(sal_Int32 nSet);
374 
375     static const SwDBData& GetAddressDBName();
376 
377     static OUString GetDBField(
378                     css::uno::Reference< css::beans::XPropertySet > const & xColumnProp,
379                     const SwDBFormatData& rDBFormatData,
380                     double *pNumber = nullptr);
381 
382     static css::uno::Reference< css::sdbc::XConnection>
383             GetConnection(const OUString& rDataSource,
384                 css::uno::Reference< css::sdbc::XDataSource>& rxSource,
385                 const SwView* pView);
386 
387     static css::uno::Reference< css::sdbcx::XColumnsSupplier>
388             GetColumnSupplier(css::uno::Reference< css::sdbc::XConnection> const & xConnection,
389                                     const OUString& rTableOrQuery,
390                                     SwDBSelect eTableOrQuery = SwDBSelect::UNKNOWN);
391 
392     static css::uno::Sequence<OUString> GetExistingDatabaseNames();
393 
394     /**
395      Loads a data source from file and registers it.
396 
397      This function requires GUI interaction, as it loads the data source from
398      the filename returned by a file picker and additional settings dialog.
399      In case of success it returns the registered name, otherwise an empty string.
400      */
401     static OUString            LoadAndRegisterDataSource(weld::Window* pParent, SwDocShell* pDocShell = nullptr);
402 
403     /**
404      Loads a data source from file and registers it.
405 
406      Convenience function, which calls GetDBunoURI and has just one mandatory parameter.
407      In case of success it returns the registered name, otherwise an empty string.
408      */
409     static OUString            LoadAndRegisterDataSource(const OUString& rURI, const OUString *pDestDir);
410 
411     /// Load the embedded data source of the document and also register it.
412     void LoadAndRegisterEmbeddedDataSource(const SwDBData& rData, const SwDocShell& rDocShell);
413 
414     /// Unregister a data source.
415     static void RevokeDataSource(const OUString& rName);
416 
417     /** try to get the data source from the given connection through the XChild interface.
418         If this is not possible, the data source will be created through its name.
419         @param _xConnection
420             The connection which should support the XChild interface. (not a must)
421         @param _sDataSourceName
422             The data source name will be used to create the data source when the connection can not be used for it.
423         @return
424             The data source.
425     */
426     static css::uno::Reference< css::sdbc::XDataSource>
427             getDataSourceAsParent(const css::uno::Reference< css::sdbc::XConnection>& _xConnection,const OUString& _sDataSourceName);
428 
429     /** creates a RowSet, which must be disposed after use.
430         @param  _sDataSourceName
431             The data source name
432         @param  _sCommand
433             The command.
434         @param  _nCommandType
435             The type of the command.
436         @param  _xConnection
437             The active connection which may be <NULL/>.
438         @return
439             The new created RowSet.
440 
441     */
442     static css::uno::Reference< css::sdbc::XResultSet>
443             createCursor(const OUString& _sDataSourceName,
444                          const OUString& _sCommand,
445                          sal_Int32 _nCommandType,
446                          const css::uno::Reference< css::sdbc::XConnection>& _xConnection,
447                          const SwView* pView);
448 
449     void setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDocShell);
450     const OUString& getEmbeddedName() const;
451 
452     // rOwnURL should be taken using INetURLObject::GetMainURL(INetURLObject::DecodeMechanism::NONE)
453     static void StoreEmbeddedDataSource(const css::uno::Reference<css::frame::XStorable>& xStorable,
454                                         const css::uno::Reference<css::embed::XStorage>& xStorage,
455                                         const OUString& rStreamRelPath,
456                                         const OUString& rOwnURL, bool bCopyTo = false);
457 
458     SwDoc* getDoc() const;
459     /// Stop reacting to removed database registrations.
460     void releaseRevokeListener();
461 
462     /// Revoke not committed registrations in case of mail merge cancel
463     void RevokeLastRegistrations();
464 
465     /// Accept not committed registrations
466     void CommitLastRegistrations();
467 
468     /// Remove not used connections.
469     void RevokeNotUsedConnections();
470 };
471 
472 namespace sw
473 {
474 enum class DBConnURIType
475 {
476     UNKNOWN = 0,
477     ODB,
478     CALC,
479     DBASE,
480     FLAT,
481     MSJET,
482     MSACE,
483     WRITER
484 };
485 
486 DBConnURIType SW_DLLPUBLIC GetDBunoType(const INetURLObject &rURL);
487 }
488 
489 #endif
490 
491 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
492