/* -*- 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: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.