LibreOffice Module reportdesign (master) 1
xmlImportDocumentHandler.cxx
Go to the documentation of this file.
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
20#include <memory>
22#include <com/sun/star/sdb/CommandType.hpp>
23#include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
24#include <com/sun/star/chart2/data/XDataReceiver.hpp>
25#include <com/sun/star/chart2/data/XDataSource.hpp>
26#include <com/sun/star/chart/XComplexDescriptionAccess.hpp>
27#include <com/sun/star/chart/ChartDataRowSource.hpp>
28#include <com/sun/star/reflection/ProxyFactory.hpp>
33#include <utility>
34#include <xmloff/xmltoken.hxx>
35#include <xmloff/xmlement.hxx>
36#include <xmloff/xmluconv.hxx>
37#include <xmloff/xmltkmap.hxx>
40#include <rtl/ref.hxx>
41
42#include "xmlHelper.hxx"
43#include "xmlEnums.hxx"
45
46namespace rptxml
47{
48using namespace ::com::sun::star;
49using namespace ::xmloff::token;
50
51ImportDocumentHandler::ImportDocumentHandler(uno::Reference< uno::XComponentContext > context)
52 :m_bImportedChart( false )
53 ,m_xContext(std::move(context))
54{
55}
56
57ImportDocumentHandler::~ImportDocumentHandler()
58{
59 if ( m_xProxy.is() )
60 {
61 m_xProxy->setDelegator( nullptr );
62 m_xProxy.clear();
63 }
64}
66
67OUString SAL_CALL ImportDocumentHandler::getImplementationName( )
68{
69 return "com.sun.star.comp.report.ImportDocumentHandler";
70}
71
72sal_Bool SAL_CALL ImportDocumentHandler::supportsService( const OUString& ServiceName )
73{
75}
76
77uno::Sequence< OUString > SAL_CALL ImportDocumentHandler::getSupportedServiceNames( )
78{
79 uno::Sequence< OUString > aSupported;
80 if ( m_xServiceInfo.is() )
81 aSupported = m_xServiceInfo->getSupportedServiceNames();
82 return ::comphelper::concatSequences( uno::Sequence<OUString> { "com.sun.star.report.ImportDocumentHandler" }, aSupported);
83}
84
85
86extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
88 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
89{
90 return cppu::acquire(new ImportDocumentHandler(context));
91}
92
93// xml::sax::XDocumentHandler:
94void SAL_CALL ImportDocumentHandler::startDocument()
95{
96 m_xDelegatee->startDocument();
97}
98
99void SAL_CALL ImportDocumentHandler::endDocument()
100{
101 m_xDelegatee->endDocument();
102 uno::Reference< chart2::data::XDataReceiver > xReceiver(m_xModel,uno::UNO_QUERY_THROW);
103 if ( !m_bImportedChart )
104 return;
105
106 // this fills the chart again
108 aArgs.put( "CellRangeRepresentation", OUString("all") );
109 aArgs.put( "FirstCellAsLabel", uno::Any( true ) );
110 aArgs.put( "DataRowSource", uno::Any( chart::ChartDataRowSource_COLUMNS ) );
111
112 bool bHasCategories = false;
113
114 uno::Reference< chart2::data::XDataSource > xDataSource(m_xModel, uno::UNO_QUERY);
115 if( xDataSource.is())
116 {
117 const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(xDataSource->getDataSequences());
118 for( const auto& rSequence : aSequences )
119 {
120 if( rSequence.is() )
121 {
122 uno::Reference< beans::XPropertySet > xSeqProp( rSequence->getValues(), uno::UNO_QUERY );
123 OUString aRole;
124 if ( xSeqProp.is()
125 && ( xSeqProp->getPropertyValue( "Role" ) >>= aRole )
126 && aRole == "categories"
127 )
128 {
129 bHasCategories = true;
130 break;
131 }
132 }
133 }
134 }
135 aArgs.put( "HasCategories", uno::Any( bHasCategories ) );
136
137 uno::Reference< chart::XComplexDescriptionAccess > xDataProvider(m_xModel->getDataProvider(),uno::UNO_QUERY);
138 if ( xDataProvider.is() )
139 {
140 const uno::Sequence< OUString > aColumnNames = xDataProvider->getColumnDescriptions();
141 aArgs.put( "ColumnDescriptions", uno::Any( aColumnNames ) );
142 }
143
144 xReceiver->attachDataProvider( m_xDatabaseDataProvider );
145 xReceiver->setArguments( aArgs.getPropertyValues() );
146}
147
148void SAL_CALL ImportDocumentHandler::startElement(const OUString & _sName, const uno::Reference< xml::sax::XAttributeList > & _xAttrList)
149{
150 uno::Reference< xml::sax::XAttributeList > xNewAttribs = _xAttrList;
151 bool bExport = true;
152 if ( _sName == "office:report" )
153 {
154 const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
155 static const OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
156 try
157 {
158 for(sal_Int16 i = 0; i < nLength; ++i)
159 {
160 OUString sLocalName;
161 const OUString sAttrName = _xAttrList->getNameByIndex( i );
162 const sal_Int32 nColonPos = sAttrName.indexOf( ':' );
163 if( -1 == nColonPos )
164 sLocalName = sAttrName;
165 else
166 sLocalName = sAttrName.copy( nColonPos + 1 );
167 const OUString sValue = _xAttrList->getValueByIndex( i );
168
169 switch( m_pReportElemTokenMap->Get( XML_NAMESPACE_REPORT, sLocalName ) )
170 {
172 {
173 sal_Int32 nRet = sdb::CommandType::COMMAND;
174 const SvXMLEnumMapEntry<sal_Int32>* aXML_EnumMap = OXMLHelper::GetCommandTypeOptions();
175 (void)SvXMLUnitConverter::convertEnum( nRet, sValue, aXML_EnumMap );
176 m_xDatabaseDataProvider->setCommandType(nRet);
177 }
178 break;
179 case XML_TOK_COMMAND:
180 m_xDatabaseDataProvider->setCommand(sValue);
181 break;
182 case XML_TOK_FILTER:
183 m_xDatabaseDataProvider->setFilter(sValue);
184 break;
186 m_xDatabaseDataProvider->setEscapeProcessing(sValue == s_sTRUE);
187 break;
188 default:
189 break;
190 }
191 }
192 }
193 catch(uno::Exception&)
194 {
195 }
196 m_xDelegatee->startElement(lcl_createAttribute(XML_NP_OFFICE,XML_CHART),nullptr);
197 bExport = false;
198 m_bImportedChart = true;
199 }
200 else if ( _sName == "rpt:master-detail-field" )
201 {
202 const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
203 ::std::unique_ptr<SvXMLTokenMap> pMasterElemTokenMap( OXMLHelper::GetSubDocumentElemTokenMap());
204 try
205 {
206 OUString sMasterField,sDetailField;
207 for(sal_Int16 i = 0; i < nLength; ++i)
208 {
209 OUString sLocalName;
210 const OUString sAttrName = _xAttrList->getNameByIndex( i );
211 const sal_Int32 nColonPos = sAttrName.indexOf( ':' );
212 if( -1 == nColonPos )
213 sLocalName = sAttrName;
214 else
215 sLocalName = sAttrName.copy( nColonPos + 1 );
216 const OUString sValue = _xAttrList->getValueByIndex( i );
217
218 switch( pMasterElemTokenMap->Get( XML_NAMESPACE_REPORT, sLocalName ) )
219 {
220 case XML_TOK_MASTER:
221 sMasterField = sValue;
222 break;
224 sDetailField = sValue;
225 break;
226 }
227 }
228 if ( sDetailField.isEmpty() )
229 sDetailField = sMasterField;
230 m_aMasterFields.push_back(sMasterField);
231 m_aDetailFields.push_back(sDetailField);
232 }
233 catch(uno::Exception&)
234 {
235 TOOLS_WARN_EXCEPTION( "reportdesign", "Exception caught while filling the report definition props");
236 }
237 bExport = false;
238 }
239 else if ( _sName == "rpt:detail"
240 || _sName == "rpt:formatted-text"
241 || _sName == "rpt:master-detail-fields"
242 || _sName == "rpt:report-component"
243 || _sName == "rpt:report-element")
244 bExport = false;
245 else if ( _sName == "chart:plot-area" )
246 {
247 bool bHasCategories = true;
248 const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
249 for(sal_Int16 i = 0; i < nLength; ++i)
250 {
251 std::u16string_view sLocalName;
252 const OUString sAttrName = _xAttrList->getNameByIndex( i );
253 const sal_Int32 nColonPos = sAttrName.indexOf( ':' );
254 if( -1 == nColonPos )
255 sLocalName = sAttrName;
256 else
257 sLocalName = sAttrName.subView( nColonPos + 1 );
258 if ( sLocalName == u"data-source-has-labels" )
259 {
260 const OUString sValue = _xAttrList->getValueByIndex( i );
261 bHasCategories = sValue == "both";
262 break;
263 }
264 }
265 for(beans::PropertyValue & propVal : asNonConstRange(m_aArguments))
266 {
267 if ( propVal.Name == "HasCategories" )
268 {
269 propVal.Value <<= bHasCategories;
270 break;
271 }
272 }
273
275 xNewAttribs = pList;
276 pList->AppendAttributeList(_xAttrList);
277 pList->AddAttribute("table:cell-range-address","local-table.$A$1:.$Z$65536");
278
279 }
280
281 if ( bExport )
282 m_xDelegatee->startElement(_sName,xNewAttribs);
283}
284
285void SAL_CALL ImportDocumentHandler::endElement(const OUString & _sName)
286{
287 bool bExport = true;
288 OUString sNewName = _sName;
289 if ( _sName == "office:report" )
290 {
292 }
293 else if ( _sName == "rpt:master-detail-fields" )
294 {
295 if ( !m_aMasterFields.empty() )
296 m_xDatabaseDataProvider->setMasterFields(uno::Sequence< OUString>(&*m_aMasterFields.begin(),m_aMasterFields.size()));
297 if ( !m_aDetailFields.empty() )
298 m_xDatabaseDataProvider->setDetailFields(uno::Sequence< OUString>(&*m_aDetailFields.begin(),m_aDetailFields.size()));
299 bExport = false;
300 }
301 else if ( _sName == "rpt:detail"
302 || _sName == "rpt:formatted-text"
303 || _sName == "rpt:master-detail-field"
304 || _sName == "rpt:report-component"
305 || _sName == "rpt:report-element")
306 bExport = false;
307
308 if ( bExport )
309 m_xDelegatee->endElement(sNewName);
310}
311
312void SAL_CALL ImportDocumentHandler::characters(const OUString & aChars)
313{
314 m_xDelegatee->characters(aChars);
315}
316
317void SAL_CALL ImportDocumentHandler::ignorableWhitespace(const OUString & aWhitespaces)
318{
319 m_xDelegatee->ignorableWhitespace(aWhitespaces);
320}
321
322void SAL_CALL ImportDocumentHandler::processingInstruction(const OUString & aTarget, const OUString & aData)
323{
324 m_xDelegatee->processingInstruction(aTarget,aData);
325}
326
327void SAL_CALL ImportDocumentHandler::setDocumentLocator(const uno::Reference< xml::sax::XLocator > & xLocator)
328{
329 m_xDelegatee->setDocumentLocator(xLocator);
330}
331void SAL_CALL ImportDocumentHandler::initialize( const uno::Sequence< uno::Any >& _aArguments )
332{
333 std::unique_lock aGuard(m_aMutex);
334 comphelper::SequenceAsHashMap aArgs(_aArguments);
335 m_xDocumentHandler = aArgs.getUnpackedValueOrDefault("DocumentHandler",m_xDocumentHandler);
337
338 OSL_ENSURE(m_xDocumentHandler.is(), "No document handler available!");
339 if (!m_xDocumentHandler.is() || !m_xModel.is())
340 throw uno::Exception("no delegatee and no model", nullptr);
341
342 m_xDelegatee.set(new SvXMLLegacyToFastDocHandler(dynamic_cast<SvXMLImport*>(m_xDocumentHandler.get())));
343
344 m_xDatabaseDataProvider.set(m_xModel->getDataProvider(),uno::UNO_QUERY);
345 if ( !m_xDatabaseDataProvider.is() )
346 {
347 // tdf#117162 reportbuilder needs the DataProvider to exist to progress further
348 setDataProvider(m_xModel, OUString());
349 m_xDatabaseDataProvider.set(m_xModel->getDataProvider(), uno::UNO_QUERY_THROW);
350 }
351
352 m_aArguments = m_xDatabaseDataProvider->detectArguments(nullptr);
353
354 uno::Reference< reflection::XProxyFactory > xProxyFactory = reflection::ProxyFactory::create( m_xContext );
355 m_xProxy = xProxyFactory->createProxy(m_xDelegatee);
356 ::comphelper::query_aggregation(m_xProxy,m_xDelegatee);
357 m_xTypeProvider.set(m_xDelegatee,uno::UNO_QUERY);
358 m_xServiceInfo.set(m_xDelegatee,uno::UNO_QUERY);
359
360 // set ourself as delegator
361 m_xProxy->setDelegator( *this );
362
363 m_pReportElemTokenMap = OXMLHelper::GetReportElemTokenMap();
364}
365
366uno::Any SAL_CALL ImportDocumentHandler::queryInterface( const uno::Type& _rType )
367{
368 uno::Any aReturn = ImportDocumentHandler_BASE::queryInterface(_rType);
369 return aReturn.hasValue() ? aReturn : (m_xProxy.is() ? m_xProxy->queryAggregation(_rType) : aReturn);
370}
371
372uno::Sequence< uno::Type > SAL_CALL ImportDocumentHandler::getTypes( )
373{
374 if ( m_xTypeProvider.is() )
375 return ::comphelper::concatSequences(
376 ImportDocumentHandler_BASE::getTypes(),
377 m_xTypeProvider->getTypes()
378 );
379 return ImportDocumentHandler_BASE::getTypes();
380}
381
382
383} // namespace rptxml
384
385
386/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
XMLOFF_DLLPUBLIC void setDataProvider(css::uno::Reference< css::chart2::XChartDocument > const &xChartDoc, OUString const &sDataPilotSource)
static bool convertEnum(EnumT &rEnum, std::u16string_view rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
bool put(const OUString &_rValueName, const VALUE_TYPE &_rValue)
css::uno::Sequence< css::beans::PropertyValue > getPropertyValues() const
TValueType getUnpackedValueOrDefault(const OUString &sKey, const TValueType &aDefault) const
ImportDocumentHandler(css::uno::Reference< css::uno::XComponentContext > context)
#define TOOLS_WARN_EXCEPTION(area, stream)
Reference< frame::XModel > m_xModel
float u
std::mutex m_aMutex
constexpr OUStringLiteral aData
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
@ XML_TOK_SUB_DETAIL
Definition: xmlEnums.hxx:54
@ XML_TOK_MASTER
Definition: xmlEnums.hxx:53
@ XML_TOK_COMMAND
Definition: xmlEnums.hxx:37
@ XML_TOK_FILTER
Definition: xmlEnums.hxx:38
@ XML_TOK_COMMAND_TYPE
Definition: xmlEnums.hxx:36
@ XML_TOK_ESCAPE_PROCESSING
Definition: xmlEnums.hxx:40
OUString lcl_createAttribute(const xmloff::token::XMLTokenEnum &_eNamespace, const xmloff::token::XMLTokenEnum &_eAttribute)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * reportdesign_ImportDocumentHandler_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
IMPLEMENT_GET_IMPLEMENTATION_ID(DrawController)
XML_TRUE
XML_NP_OFFICE
XML_CHART
bool hasValue()
unsigned char sal_Bool
constexpr sal_uInt16 XML_NAMESPACE_REPORT
sal_Int32 nLength