/src/libreoffice/sc/source/ui/dataprovider/dataprovider.cxx
Line | Count | Source |
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 | | |
10 | | #include <dataprovider.hxx> |
11 | | #include <com/sun/star/ucb/XSimpleFileAccess3.hpp> |
12 | | #include <com/sun/star/ucb/SimpleFileAccess.hpp> |
13 | | #include <com/sun/star/io/XInputStream.hpp> |
14 | | #include <o3tl/string_view.hxx> |
15 | | #include <rtl/strbuf.hxx> |
16 | | #include <sal/log.hxx> |
17 | | #include <unotools/charclass.hxx> |
18 | | #include <tools/stream.hxx> |
19 | | #include <comphelper/processfactory.hxx> |
20 | | |
21 | | #include "htmldataprovider.hxx" |
22 | | #include "xmldataprovider.hxx" |
23 | | #include "sqldataprovider.hxx" |
24 | | #include <datamapper.hxx> |
25 | | #include <dbdata.hxx> |
26 | | #include <docsh.hxx> |
27 | | #include <utility> |
28 | | |
29 | | using namespace com::sun::star; |
30 | | |
31 | | namespace sc { |
32 | | |
33 | | std::unique_ptr<SvStream> DataProvider::FetchStreamFromURL(const OUString& rURL, OStringBuffer& rBuffer) |
34 | 0 | { |
35 | 0 | try |
36 | 0 | { |
37 | 0 | uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ); |
38 | |
|
39 | 0 | uno::Reference< io::XInputStream > xStream = xFileAccess->openFileRead( rURL ); |
40 | |
|
41 | 0 | const sal_Int32 BUF_LEN = 8000; |
42 | 0 | uno::Sequence< sal_Int8 > buffer( BUF_LEN ); |
43 | |
|
44 | 0 | sal_Int32 nRead = 0; |
45 | 0 | while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN ) |
46 | 0 | { |
47 | 0 | rBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead ); |
48 | 0 | } |
49 | |
|
50 | 0 | if ( nRead > 0 ) |
51 | 0 | { |
52 | 0 | rBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead ); |
53 | 0 | } |
54 | |
|
55 | 0 | xStream->closeInput(); |
56 | |
|
57 | 0 | SvStream* pStream = new SvMemoryStream(const_cast<char*>(rBuffer.getStr()), rBuffer.getLength(), StreamMode::READ); |
58 | 0 | return std::unique_ptr<SvStream>(pStream); |
59 | 0 | } |
60 | 0 | catch(...) |
61 | 0 | { |
62 | 0 | rBuffer.setLength(0); |
63 | 0 | return nullptr; |
64 | 0 | } |
65 | 0 | } |
66 | | |
67 | | ExternalDataSource::ExternalDataSource(OUString aURL, |
68 | | OUString aProvider, ScDocument* pDoc) |
69 | 0 | : maURL(std::move(aURL)) |
70 | 0 | , maProvider(std::move(aProvider)) |
71 | 0 | , mpDoc(pDoc) |
72 | 0 | { |
73 | 0 | } |
74 | | |
75 | | void ExternalDataSource::setID(const OUString& rID) |
76 | 0 | { |
77 | 0 | maID = rID; |
78 | 0 | } |
79 | | |
80 | | void ExternalDataSource::setXMLImportParam(const ScOrcusImportXMLParam& rParam) |
81 | 0 | { |
82 | 0 | maParam = rParam; |
83 | 0 | } |
84 | | |
85 | | |
86 | | |
87 | | void ExternalDataSource::setURL(const OUString& rURL) |
88 | 0 | { |
89 | 0 | maURL = rURL; |
90 | 0 | } |
91 | | |
92 | | void ExternalDataSource::setProvider(const OUString& rProvider) |
93 | 0 | { |
94 | 0 | maProvider = rProvider; |
95 | 0 | mpDataProvider.reset(); |
96 | 0 | } |
97 | | |
98 | | const OUString& ExternalDataSource::getURL() const |
99 | 0 | { |
100 | 0 | return maURL; |
101 | 0 | } |
102 | | |
103 | | const OUString& ExternalDataSource::getProvider() const |
104 | 0 | { |
105 | 0 | return maProvider; |
106 | 0 | } |
107 | | |
108 | | const OUString& ExternalDataSource::getID() const |
109 | 0 | { |
110 | 0 | return maID; |
111 | 0 | } |
112 | | |
113 | | const ScOrcusImportXMLParam& ExternalDataSource::getXMLImportParam() const |
114 | 0 | { |
115 | 0 | return maParam; |
116 | 0 | } |
117 | | |
118 | | OUString ExternalDataSource::getDBName() const |
119 | 0 | { |
120 | 0 | if (mpDBDataManager) |
121 | 0 | { |
122 | 0 | ScDBData* pDBData = mpDBDataManager->getDBData(); |
123 | 0 | if (pDBData) |
124 | 0 | return pDBData->GetName(); |
125 | 0 | } |
126 | 0 | return OUString(); |
127 | 0 | } |
128 | | |
129 | | void ExternalDataSource::setDBData(const OUString& rDBName) |
130 | 0 | { |
131 | 0 | if (!mpDBDataManager) |
132 | 0 | { |
133 | 0 | mpDBDataManager = std::make_shared<ScDBDataManager>(rDBName, mpDoc); |
134 | 0 | } |
135 | 0 | else |
136 | 0 | { |
137 | 0 | mpDBDataManager->SetDatabase(rDBName); |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | | double ExternalDataSource::getUpdateFrequency() |
142 | 0 | { |
143 | 0 | return 0; |
144 | 0 | } |
145 | | |
146 | | ScDBDataManager* ExternalDataSource::getDBManager() |
147 | 0 | { |
148 | 0 | return mpDBDataManager.get(); |
149 | 0 | } |
150 | | |
151 | | void ExternalDataSource::refresh(ScDocument* pDoc, bool bDeterministic) |
152 | 0 | { |
153 | | // no DB data available |
154 | 0 | if (!mpDBDataManager) |
155 | 0 | return; |
156 | | |
157 | | // tdf#169541 An existing mpDataProvider might have a corrupted backreference to `this`. |
158 | | // Thus create a new one in any case. |
159 | 0 | mpDataProvider = DataProviderFactory::getDataProvider(pDoc, *this); |
160 | | |
161 | | // if we have not been able to create one, we can not refresh the data |
162 | 0 | if (!mpDataProvider) |
163 | 0 | return; |
164 | | |
165 | 0 | if (bDeterministic) |
166 | 0 | mpDataProvider->setDeterministic(); |
167 | |
|
168 | 0 | mpDataProvider->Import(); |
169 | 0 | } |
170 | | |
171 | | void ExternalDataSource::AddDataTransformation( |
172 | | const std::shared_ptr<sc::DataTransformation>& mpDataTransformation) |
173 | 0 | { |
174 | 0 | maDataTransformations.push_back(mpDataTransformation); |
175 | 0 | } |
176 | | |
177 | | const std::vector<std::shared_ptr<sc::DataTransformation>>& ExternalDataSource::getDataTransformation() const |
178 | 0 | { |
179 | 0 | return maDataTransformations; |
180 | 0 | } |
181 | | |
182 | | ExternalDataMapper::ExternalDataMapper(ScDocument& /*rDoc*/) |
183 | | //mrDoc(rDoc) |
184 | 0 | { |
185 | 0 | } |
186 | | |
187 | | ExternalDataMapper::~ExternalDataMapper() |
188 | 0 | { |
189 | 0 | } |
190 | | |
191 | | void ExternalDataMapper::insertDataSource(const sc::ExternalDataSource& rSource) |
192 | 0 | { |
193 | 0 | maDataSources.push_back(rSource); |
194 | 0 | } |
195 | | |
196 | | const std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources() const |
197 | 0 | { |
198 | 0 | return maDataSources; |
199 | 0 | } |
200 | | |
201 | | std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources() |
202 | 0 | { |
203 | 0 | return maDataSources; |
204 | 0 | } |
205 | | |
206 | | DataProvider::DataProvider(sc::ExternalDataSource& rDataSource): |
207 | 0 | mbDeterministic(false), |
208 | 0 | mrDataSource(rDataSource) |
209 | 0 | { |
210 | 0 | } |
211 | | |
212 | | void DataProvider::setDeterministic() |
213 | 0 | { |
214 | 0 | mbDeterministic = true; |
215 | 0 | } |
216 | | |
217 | | DataProvider::~DataProvider() |
218 | 0 | { |
219 | 0 | } |
220 | | |
221 | | void ScDBDataManager::WriteToDoc(ScDocument& rDoc) |
222 | 0 | { |
223 | | // first apply all data transformations |
224 | |
|
225 | 0 | bool bShrunk = false; |
226 | 0 | SCCOL nStartCol = 0; |
227 | 0 | SCROW nStartRow = 0; |
228 | 0 | SCCOL nEndCol = rDoc.MaxCol(); |
229 | 0 | SCROW nEndRow = rDoc.MaxRow(); |
230 | 0 | rDoc.ShrinkToUsedDataArea(bShrunk, 0, nStartCol, nStartRow, nEndCol, nEndRow, false, true, true); |
231 | 0 | ScRange aClipRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0); |
232 | 0 | rDoc.SetClipArea(aClipRange); |
233 | |
|
234 | 0 | ScRange aDestRange; |
235 | 0 | getDBData()->GetArea(aDestRange); |
236 | 0 | SCCOL nColSize = std::min<SCCOL>(aDestRange.aEnd.Col() - aDestRange.aStart.Col(), nEndCol); |
237 | 0 | aDestRange.aEnd.SetCol(aDestRange.aStart.Col() + nColSize); |
238 | |
|
239 | 0 | SCROW nRowSize = std::min<SCROW>(aDestRange.aEnd.Row() - aDestRange.aStart.Row(), nEndRow); |
240 | 0 | aDestRange.aEnd.SetRow(aDestRange.aStart.Row() + nRowSize); |
241 | |
|
242 | 0 | ScMarkData aMark(mpDoc->GetSheetLimits()); |
243 | 0 | aMark.SelectTable(aDestRange.aStart.Tab(), true); |
244 | 0 | mpDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::CONTENTS, nullptr, &rDoc); |
245 | 0 | ScDocShell* pDocShell = mpDoc->GetDocumentShell(); |
246 | 0 | if (pDocShell) |
247 | 0 | pDocShell->PostPaint(aDestRange, PaintPartFlags::All); |
248 | 0 | } |
249 | | |
250 | | ScDBDataManager::ScDBDataManager(OUString aDBName, ScDocument* pDoc): |
251 | 0 | maDBName(std::move(aDBName)), |
252 | 0 | mpDoc(pDoc) |
253 | 0 | { |
254 | 0 | } |
255 | | |
256 | | ScDBDataManager::~ScDBDataManager() |
257 | 0 | { |
258 | 0 | } |
259 | | |
260 | | void ScDBDataManager::SetDatabase(const OUString& rDBName) |
261 | 0 | { |
262 | 0 | maDBName = rDBName; |
263 | 0 | } |
264 | | |
265 | | ScDBData* ScDBDataManager::getDBData() |
266 | 0 | { |
267 | 0 | ScDBData* pDBData = mpDoc->GetDBCollection()->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(maDBName)); |
268 | 0 | return pDBData; |
269 | 0 | } |
270 | | |
271 | | bool DataProviderFactory::isInternalDataProvider(std::u16string_view rProvider) |
272 | 0 | { |
273 | 0 | return o3tl::starts_with(rProvider, u"org.libreoffice.calc"); |
274 | 0 | } |
275 | | |
276 | | std::shared_ptr<DataProvider> DataProviderFactory::getDataProvider(ScDocument* pDoc, |
277 | | sc::ExternalDataSource& rDataSource) |
278 | 0 | { |
279 | 0 | const OUString& rDataProvider = rDataSource.getProvider(); |
280 | 0 | bool bInternal = DataProviderFactory::isInternalDataProvider(rDataProvider); |
281 | 0 | if (bInternal) |
282 | 0 | { |
283 | 0 | if (rDataProvider == "org.libreoffice.calc.csv") |
284 | 0 | return std::make_shared<CSVDataProvider>(pDoc, rDataSource); |
285 | 0 | else if (rDataProvider == "org.libreoffice.calc.html") |
286 | 0 | return std::make_shared<HTMLDataProvider>(pDoc, rDataSource); |
287 | 0 | else if (rDataProvider == "org.libreoffice.calc.xml") |
288 | 0 | return std::make_shared<XMLDataProvider>(pDoc, rDataSource); |
289 | 0 | else if (rDataProvider == "org.libreoffice.calc.sql") |
290 | 0 | return std::make_shared<SQLDataProvider>(pDoc, rDataSource); |
291 | 0 | } |
292 | 0 | else |
293 | 0 | { |
294 | 0 | SAL_WARN("sc", "no external data provider supported yet"); |
295 | 0 | return std::shared_ptr<DataProvider>(); |
296 | 0 | } |
297 | | |
298 | 0 | return std::shared_ptr<DataProvider>(); |
299 | 0 | } |
300 | | |
301 | | } |
302 | | |
303 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |