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