314 lines
8.2 KiB
C++
314 lines
8.2 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <dataprovider.hxx>
|
|
#include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
|
|
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
|
|
#include <com/sun/star/io/XInputStream.hpp>
|
|
#include <o3tl/string_view.hxx>
|
|
#include <rtl/strbuf.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <unotools/charclass.hxx>
|
|
#include <tools/stream.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
|
|
#include "htmldataprovider.hxx"
|
|
#include "xmldataprovider.hxx"
|
|
#include "sqldataprovider.hxx"
|
|
#include <datamapper.hxx>
|
|
#include <dbdata.hxx>
|
|
#include <docsh.hxx>
|
|
#include <utility>
|
|
|
|
using namespace com::sun::star;
|
|
|
|
namespace sc {
|
|
|
|
std::unique_ptr<SvStream> DataProvider::FetchStreamFromURL(const OUString& rURL, OStringBuffer& rBuffer)
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
|
|
|
|
uno::Reference< io::XInputStream > xStream = xFileAccess->openFileRead( rURL );
|
|
|
|
const sal_Int32 BUF_LEN = 8000;
|
|
uno::Sequence< sal_Int8 > buffer( BUF_LEN );
|
|
|
|
sal_Int32 nRead = 0;
|
|
while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN )
|
|
{
|
|
rBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
|
|
}
|
|
|
|
if ( nRead > 0 )
|
|
{
|
|
rBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
|
|
}
|
|
|
|
xStream->closeInput();
|
|
|
|
SvStream* pStream = new SvMemoryStream(const_cast<char*>(rBuffer.getStr()), rBuffer.getLength(), StreamMode::READ);
|
|
return std::unique_ptr<SvStream>(pStream);
|
|
}
|
|
catch(...)
|
|
{
|
|
rBuffer.setLength(0);
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
ExternalDataSource::ExternalDataSource(OUString aURL,
|
|
OUString aProvider, ScDocument* pDoc)
|
|
: maURL(std::move(aURL))
|
|
, maProvider(std::move(aProvider))
|
|
, mpDoc(pDoc)
|
|
{
|
|
}
|
|
|
|
void ExternalDataSource::setID(const OUString& rID)
|
|
{
|
|
maID = rID;
|
|
}
|
|
|
|
void ExternalDataSource::setXMLImportParam(const ScOrcusImportXMLParam& rParam)
|
|
{
|
|
maParam = rParam;
|
|
}
|
|
|
|
|
|
|
|
void ExternalDataSource::setURL(const OUString& rURL)
|
|
{
|
|
maURL = rURL;
|
|
}
|
|
|
|
void ExternalDataSource::setProvider(const OUString& rProvider)
|
|
{
|
|
maProvider = rProvider;
|
|
mpDataProvider.reset();
|
|
}
|
|
|
|
const OUString& ExternalDataSource::getURL() const
|
|
{
|
|
return maURL;
|
|
}
|
|
|
|
const OUString& ExternalDataSource::getProvider() const
|
|
{
|
|
return maProvider;
|
|
}
|
|
|
|
const OUString& ExternalDataSource::getID() const
|
|
{
|
|
return maID;
|
|
}
|
|
|
|
const ScOrcusImportXMLParam& ExternalDataSource::getXMLImportParam() const
|
|
{
|
|
return maParam;
|
|
}
|
|
|
|
OUString ExternalDataSource::getDBName() const
|
|
{
|
|
if (mpDBDataManager)
|
|
{
|
|
ScDBData* pDBData = mpDBDataManager->getDBData();
|
|
if (pDBData)
|
|
return pDBData->GetName();
|
|
}
|
|
return OUString();
|
|
}
|
|
|
|
void ExternalDataSource::setDBData(const OUString& rDBName)
|
|
{
|
|
if (!mpDBDataManager)
|
|
{
|
|
mpDBDataManager = std::make_shared<ScDBDataManager>(rDBName, mpDoc);
|
|
}
|
|
else
|
|
{
|
|
mpDBDataManager->SetDatabase(rDBName);
|
|
}
|
|
}
|
|
|
|
double ExternalDataSource::getUpdateFrequency()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ScDBDataManager* ExternalDataSource::getDBManager()
|
|
{
|
|
return mpDBDataManager.get();
|
|
}
|
|
|
|
void ExternalDataSource::refresh(ScDocument* pDoc, bool bDeterministic)
|
|
{
|
|
// no DB data available
|
|
if (!mpDBDataManager)
|
|
return;
|
|
|
|
// if no data provider exists, try to create one
|
|
if (!mpDataProvider)
|
|
mpDataProvider = DataProviderFactory::getDataProvider(pDoc, *this);
|
|
|
|
// if we still have not been able to create one, we can not refresh the data
|
|
if (!mpDataProvider)
|
|
return;
|
|
|
|
if (bDeterministic)
|
|
mpDataProvider->setDeterministic();
|
|
|
|
mpDataProvider->Import();
|
|
}
|
|
|
|
void ExternalDataSource::AddDataTransformation(
|
|
const std::shared_ptr<sc::DataTransformation>& mpDataTransformation)
|
|
{
|
|
maDataTransformations.push_back(mpDataTransformation);
|
|
}
|
|
|
|
const std::vector<std::shared_ptr<sc::DataTransformation>>& ExternalDataSource::getDataTransformation() const
|
|
{
|
|
return maDataTransformations;
|
|
}
|
|
|
|
ExternalDataMapper::ExternalDataMapper(ScDocument& /*rDoc*/)
|
|
//mrDoc(rDoc)
|
|
{
|
|
}
|
|
|
|
ExternalDataMapper::~ExternalDataMapper()
|
|
{
|
|
}
|
|
|
|
void ExternalDataMapper::insertDataSource(const sc::ExternalDataSource& rSource)
|
|
{
|
|
maDataSources.push_back(rSource);
|
|
}
|
|
|
|
const std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources() const
|
|
{
|
|
return maDataSources;
|
|
}
|
|
|
|
std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources()
|
|
{
|
|
return maDataSources;
|
|
}
|
|
|
|
DataProvider::DataProvider(sc::ExternalDataSource& rDataSource):
|
|
mbDeterministic(false),
|
|
mrDataSource(rDataSource)
|
|
{
|
|
}
|
|
|
|
void DataProvider::setDeterministic()
|
|
{
|
|
mbDeterministic = true;
|
|
}
|
|
|
|
DataProvider::~DataProvider()
|
|
{
|
|
}
|
|
|
|
void ScDBDataManager::WriteToDoc(ScDocument& rDoc)
|
|
{
|
|
// first apply all data transformations
|
|
|
|
bool bShrunk = false;
|
|
SCCOL nStartCol = 0;
|
|
SCROW nStartRow = 0;
|
|
SCCOL nEndCol = rDoc.MaxCol();
|
|
SCROW nEndRow = rDoc.MaxRow();
|
|
rDoc.ShrinkToUsedDataArea(bShrunk, 0, nStartCol, nStartRow, nEndCol, nEndRow, false, true, true);
|
|
ScRange aClipRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0);
|
|
rDoc.SetClipArea(aClipRange);
|
|
|
|
ScRange aDestRange;
|
|
getDBData()->GetArea(aDestRange);
|
|
SCCOL nColSize = std::min<SCCOL>(aDestRange.aEnd.Col() - aDestRange.aStart.Col(), nEndCol);
|
|
aDestRange.aEnd.SetCol(aDestRange.aStart.Col() + nColSize);
|
|
|
|
SCROW nRowSize = std::min<SCROW>(aDestRange.aEnd.Row() - aDestRange.aStart.Row(), nEndRow);
|
|
aDestRange.aEnd.SetRow(aDestRange.aStart.Row() + nRowSize);
|
|
|
|
ScMarkData aMark(mpDoc->GetSheetLimits());
|
|
aMark.SelectTable(0, true);
|
|
mpDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::CONTENTS, nullptr, &rDoc);
|
|
ScDocShell* pDocShell = mpDoc->GetDocumentShell();
|
|
if (pDocShell)
|
|
pDocShell->PostPaint(aDestRange, PaintPartFlags::All);
|
|
}
|
|
|
|
ScDBDataManager::ScDBDataManager(OUString aDBName, ScDocument* pDoc):
|
|
maDBName(std::move(aDBName)),
|
|
mpDoc(pDoc)
|
|
{
|
|
}
|
|
|
|
ScDBDataManager::~ScDBDataManager()
|
|
{
|
|
}
|
|
|
|
void ScDBDataManager::SetDatabase(const OUString& rDBName)
|
|
{
|
|
maDBName = rDBName;
|
|
}
|
|
|
|
ScDBData* ScDBDataManager::getDBData()
|
|
{
|
|
ScDBData* pDBData = mpDoc->GetDBCollection()->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(maDBName));
|
|
return pDBData;
|
|
}
|
|
|
|
bool DataProviderFactory::isInternalDataProvider(std::u16string_view rProvider)
|
|
{
|
|
return o3tl::starts_with(rProvider, u"org.libreoffice.calc");
|
|
}
|
|
|
|
std::shared_ptr<DataProvider> DataProviderFactory::getDataProvider(ScDocument* pDoc,
|
|
sc::ExternalDataSource& rDataSource)
|
|
{
|
|
const OUString& rDataProvider = rDataSource.getProvider();
|
|
bool bInternal = DataProviderFactory::isInternalDataProvider(rDataProvider);
|
|
if (bInternal)
|
|
{
|
|
if (rDataProvider == "org.libreoffice.calc.csv")
|
|
return std::make_shared<CSVDataProvider>(pDoc, rDataSource);
|
|
else if (rDataProvider == "org.libreoffice.calc.html")
|
|
return std::make_shared<HTMLDataProvider>(pDoc, rDataSource);
|
|
else if (rDataProvider == "org.libreoffice.calc.xml")
|
|
return std::make_shared<XMLDataProvider>(pDoc, rDataSource);
|
|
else if (rDataProvider == "org.libreoffice.calc.sql")
|
|
return std::make_shared<SQLDataProvider>(pDoc, rDataSource);
|
|
}
|
|
else
|
|
{
|
|
SAL_WARN("sc", "no external data provider supported yet");
|
|
return std::shared_ptr<DataProvider>();
|
|
}
|
|
|
|
return std::shared_ptr<DataProvider>();
|
|
}
|
|
|
|
std::vector<OUString> DataProviderFactory::getDataProviders()
|
|
{
|
|
std::vector<OUString> aDataProviders;
|
|
aDataProviders.emplace_back("org.libreoffice.calc.csv");
|
|
aDataProviders.emplace_back("org.libreoffice.calc.html");
|
|
aDataProviders.emplace_back("org.libreoffice.calc.xml");
|
|
aDataProviders.emplace_back("org.libreoffice.calc.sql");
|
|
|
|
return aDataProviders;
|
|
}
|
|
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|