Line data Source code
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 "xmlExportDocumentHandler.hxx"
21 : #include <com/sun/star/sdb/CommandType.hpp>
22 : #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
23 : #include <com/sun/star/chart/XComplexDescriptionAccess.hpp>
24 : #include <com/sun/star/reflection/ProxyFactory.hpp>
25 : #include <comphelper/sequenceashashmap.hxx>
26 : #include <comphelper/documentconstants.hxx>
27 : #include <cppuhelper/supportsservice.hxx>
28 : #include <xmloff/attrlist.hxx>
29 : #include <xmloff/xmltoken.hxx>
30 : #include <xmloff/xmlement.hxx>
31 : #include <xmloff/xmluconv.hxx>
32 : #include <unotools/saveopt.hxx>
33 : #include <rtl/ustrbuf.hxx>
34 : #include <connectivity/dbtools.hxx>
35 :
36 : namespace rptxml
37 : {
38 : using namespace ::com::sun::star;
39 : using namespace ::xmloff::token;
40 :
41 0 : void lcl_exportPrettyPrinting(const uno::Reference< xml::sax::XDocumentHandler >& _xDelegatee)
42 : {
43 0 : SvtSaveOptions aSaveOpt;
44 0 : if ( aSaveOpt.IsPrettyPrinting() )
45 : {
46 : static const char s_sWhitespaces[] = " ";
47 0 : _xDelegatee->ignorableWhitespace(s_sWhitespaces);
48 0 : }
49 0 : }
50 :
51 0 : OUString lcl_createAttribute(const xmloff::token::XMLTokenEnum& _eNamespace,const xmloff::token::XMLTokenEnum& _eAttribute)
52 : {
53 0 : OUStringBuffer sQName;
54 : // ...if it's in our map, make the prefix
55 0 : sQName.append ( xmloff::token::GetXMLToken(_eNamespace) );
56 0 : sQName.append ( ':' );
57 0 : sQName.append ( xmloff::token::GetXMLToken(_eAttribute) );
58 0 : return sQName.makeStringAndClear();
59 : }
60 :
61 0 : void lcl_correctCellAddress(const OUString & _sName, const uno::Reference< xml::sax::XAttributeList > & xAttribs)
62 : {
63 0 : SvXMLAttributeList* pList = SvXMLAttributeList::getImplementation(xAttribs);
64 0 : OUString sCellAddress = pList->getValueByName(_sName);
65 0 : const sal_Int32 nPos = sCellAddress.lastIndexOf('$');
66 0 : if ( nPos != -1 )
67 : {
68 0 : sCellAddress = sCellAddress.copy(0,nPos) + "$65535";
69 0 : pList->RemoveAttribute(_sName);
70 0 : pList->AddAttribute(_sName,sCellAddress);
71 0 : }
72 0 : }
73 :
74 0 : ExportDocumentHandler::ExportDocumentHandler(uno::Reference< uno::XComponentContext > const & context) :
75 : m_xContext(context)
76 : ,m_nColumnCount(0)
77 : ,m_bTableRowsStarted(false)
78 : ,m_bFirstRowExported(false)
79 : ,m_bExportChar(false)
80 0 : ,m_bCountColumnHeader(false)
81 : {
82 0 : }
83 :
84 0 : ExportDocumentHandler::~ExportDocumentHandler()
85 : {
86 0 : if ( m_xProxy.is() )
87 : {
88 0 : m_xProxy->setDelegator( NULL );
89 0 : m_xProxy.clear();
90 : }
91 0 : }
92 0 : IMPLEMENT_GET_IMPLEMENTATION_ID(ExportDocumentHandler)
93 0 : IMPLEMENT_FORWARD_REFCOUNT( ExportDocumentHandler, ExportDocumentHandler_BASE )
94 :
95 0 : OUString SAL_CALL ExportDocumentHandler::getImplementationName( ) throw(uno::RuntimeException, std::exception)
96 : {
97 0 : return getImplementationName_Static();
98 : }
99 :
100 0 : sal_Bool SAL_CALL ExportDocumentHandler::supportsService( const OUString& ServiceName ) throw(uno::RuntimeException, std::exception)
101 : {
102 0 : return cppu::supportsService(this, ServiceName);
103 : }
104 :
105 0 : uno::Sequence< OUString > SAL_CALL ExportDocumentHandler::getSupportedServiceNames( ) throw(uno::RuntimeException, std::exception)
106 : {
107 0 : uno::Sequence< OUString > aSupported;
108 0 : if ( m_xServiceInfo.is() )
109 0 : aSupported = m_xServiceInfo->getSupportedServiceNames();
110 0 : return ::comphelper::concatSequences(getSupportedServiceNames_static(),aSupported);
111 : }
112 :
113 7 : OUString ExportDocumentHandler::getImplementationName_Static( ) throw(uno::RuntimeException)
114 : {
115 7 : return OUString("com.sun.star.comp.report.ExportDocumentHandler");
116 : }
117 :
118 :
119 0 : uno::Sequence< OUString > ExportDocumentHandler::getSupportedServiceNames_static( ) throw(uno::RuntimeException)
120 : {
121 0 : uno::Sequence< OUString > aSupported(1);
122 0 : aSupported[0] = "com.sun.star.report.ExportDocumentHandler";
123 0 : return aSupported;
124 : }
125 :
126 :
127 0 : uno::Reference< uno::XInterface > SAL_CALL ExportDocumentHandler::create( const uno::Reference< uno::XComponentContext >& _rxContext )
128 : {
129 0 : return *(new ExportDocumentHandler( _rxContext ));
130 : }
131 : // xml::sax::XDocumentHandler:
132 0 : void SAL_CALL ExportDocumentHandler::startDocument() throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
133 : {
134 0 : m_xDelegatee->startDocument();
135 0 : }
136 :
137 0 : void SAL_CALL ExportDocumentHandler::endDocument() throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
138 : {
139 0 : m_xDelegatee->endDocument();
140 0 : }
141 :
142 0 : void SAL_CALL ExportDocumentHandler::startElement(const OUString & _sName, const uno::Reference< xml::sax::XAttributeList > & xAttribs) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
143 : {
144 0 : bool bExport = true;
145 0 : if ( _sName == "office:chart" )
146 : {
147 0 : SvXMLAttributeList* pList = new SvXMLAttributeList();
148 0 : uno::Reference< xml::sax::XAttributeList > xNewAttribs = pList;
149 0 : OUStringBuffer sValue;
150 : static const SvXMLEnumMapEntry aXML_CommnadTypeEnumMap[] =
151 : {
152 : { XML_TABLE, sdb::CommandType::TABLE },
153 : { XML_QUERY, sdb::CommandType::QUERY },
154 : { XML_TOKEN_INVALID, 0 }
155 : };
156 0 : if ( SvXMLUnitConverter::convertEnum( sValue, static_cast<sal_uInt16>(m_xDatabaseDataProvider->getCommandType()),aXML_CommnadTypeEnumMap ) )
157 : {
158 0 : pList->AddAttribute(lcl_createAttribute(XML_NP_RPT,XML_COMMAND_TYPE),sValue.makeStringAndClear());
159 : }
160 0 : const OUString sComamnd = m_xDatabaseDataProvider->getCommand();
161 0 : if ( !sComamnd.isEmpty() )
162 0 : pList->AddAttribute(lcl_createAttribute(XML_NP_RPT,XML_COMMAND),sComamnd);
163 :
164 0 : const OUString sFilter( m_xDatabaseDataProvider->getFilter() );
165 0 : if ( !sFilter.isEmpty() )
166 0 : pList->AddAttribute(lcl_createAttribute(XML_NP_RPT,XML_FILTER),sFilter);
167 :
168 0 : const bool bEscapeProcessing( m_xDatabaseDataProvider->getEscapeProcessing() );
169 0 : if ( !bEscapeProcessing )
170 0 : pList->AddAttribute(lcl_createAttribute(XML_NP_RPT,XML_ESCAPE_PROCESSING),::xmloff::token::GetXMLToken( XML_FALSE ));
171 :
172 0 : pList->AddAttribute(lcl_createAttribute(XML_NP_OFFICE,XML_MIMETYPE),MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII);
173 :
174 0 : m_xDelegatee->startElement(lcl_createAttribute(XML_NP_OFFICE,XML_REPORT),xNewAttribs);
175 :
176 0 : const OUString sTableCalc = lcl_createAttribute(XML_NP_TABLE,XML_CALCULATION_SETTINGS);
177 0 : m_xDelegatee->startElement(sTableCalc,NULL);
178 0 : pList = new SvXMLAttributeList();
179 0 : uno::Reference< xml::sax::XAttributeList > xNullAttr = pList;
180 0 : pList->AddAttribute(lcl_createAttribute(XML_NP_TABLE,XML_DATE_VALUE),OUString("1899-12-30"));
181 :
182 0 : const OUString sNullDate = lcl_createAttribute(XML_NP_TABLE,XML_NULL_DATE);
183 0 : m_xDelegatee->startElement(sNullDate,xNullAttr);
184 0 : m_xDelegatee->endElement(sNullDate);
185 0 : m_xDelegatee->endElement(sTableCalc);
186 0 : bExport = false;
187 : }
188 0 : else if ( _sName == "table:table" )
189 : {
190 0 : m_xDelegatee->startElement(lcl_createAttribute(XML_NP_RPT,XML_DETAIL),NULL);
191 0 : lcl_exportPrettyPrinting(m_xDelegatee);
192 : }
193 0 : else if ( _sName == "table:table-header-rows" )
194 : {
195 0 : m_bCountColumnHeader = true;
196 : }
197 0 : else if ( m_bCountColumnHeader && _sName == "table:table-cell" )
198 : {
199 0 : ++m_nColumnCount;
200 : }
201 0 : else if ( _sName == "table:table-rows" )
202 : {
203 0 : m_xDelegatee->startElement(_sName,xAttribs);
204 0 : exportTableRows();
205 0 : bExport = false;
206 0 : m_bTableRowsStarted = true;
207 0 : m_bFirstRowExported = true;
208 : }
209 0 : else if ( m_bTableRowsStarted && m_bFirstRowExported && (_sName == "table:table-row" || _sName == "table:table-cell") )
210 0 : bExport = false;
211 0 : else if ( _sName == "chart:plot-area" )
212 : {
213 0 : SvXMLAttributeList* pList = SvXMLAttributeList::getImplementation(xAttribs);
214 0 : pList->RemoveAttribute(OUString("table:cell-range-address"));
215 : }
216 0 : else if ( _sName == "chart:categories" )
217 : {
218 0 : static OUString s_sCellAddress(lcl_createAttribute(XML_NP_TABLE,XML_CELL_RANGE_ADDRESS));
219 0 : lcl_correctCellAddress(s_sCellAddress,xAttribs);
220 : }
221 0 : else if ( _sName == "chart:series" )
222 : {
223 0 : static OUString s_sCellAddress(lcl_createAttribute(XML_NP_CHART,XML_VALUES_CELL_RANGE_ADDRESS));
224 0 : lcl_correctCellAddress(s_sCellAddress,xAttribs);
225 : }
226 0 : else if ( m_bTableRowsStarted && !m_bFirstRowExported && _sName == "table:table-cell" )
227 : {
228 0 : SvXMLAttributeList* pList = SvXMLAttributeList::getImplementation(xAttribs);
229 0 : static OUString s_sValue(lcl_createAttribute(XML_NP_OFFICE,XML_VALUE));
230 0 : pList->RemoveAttribute(s_sValue);
231 : }
232 0 : else if ( m_bTableRowsStarted && _sName == "text:p" )
233 : {
234 0 : bExport = false;
235 : }
236 0 : if ( bExport )
237 0 : m_xDelegatee->startElement(_sName,xAttribs);
238 0 : }
239 :
240 0 : void SAL_CALL ExportDocumentHandler::endElement(const OUString & _sName) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
241 : {
242 0 : bool bExport = true;
243 0 : OUString sNewName = _sName;
244 0 : if ( _sName == "office:chart" )
245 : {
246 0 : sNewName = lcl_createAttribute(XML_NP_OFFICE,XML_REPORT);
247 : }
248 0 : else if ( _sName == "table:table" )
249 : {
250 0 : m_xDelegatee->endElement(_sName);
251 0 : lcl_exportPrettyPrinting(m_xDelegatee);
252 0 : sNewName = lcl_createAttribute(XML_NP_RPT,XML_DETAIL);
253 : }
254 0 : else if ( _sName == "table:table-header-rows" )
255 : {
256 0 : m_bCountColumnHeader = false;
257 : }
258 0 : else if ( _sName == "table:table-rows" )
259 0 : m_bTableRowsStarted = false;
260 0 : else if ( m_bTableRowsStarted && m_bFirstRowExported && (_sName == "table:table-row" || _sName == "table:table-cell") )
261 0 : bExport = false;
262 0 : else if ( m_bTableRowsStarted && _sName == "table:table-row" )
263 0 : m_bFirstRowExported = true;
264 0 : else if ( m_bTableRowsStarted && _sName == "text:p" )
265 : {
266 0 : bExport = !m_bFirstRowExported;
267 : }
268 :
269 0 : if ( bExport )
270 0 : m_xDelegatee->endElement(sNewName);
271 0 : }
272 :
273 0 : void SAL_CALL ExportDocumentHandler::characters(const OUString & aChars) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
274 : {
275 0 : if ( !(m_bTableRowsStarted || m_bFirstRowExported) )
276 : {
277 0 : m_xDelegatee->characters(aChars);
278 : }
279 0 : else if ( m_bExportChar )
280 : {
281 : static const char s_sZero[] = "0";
282 0 : m_xDelegatee->characters(s_sZero);
283 : }
284 0 : }
285 :
286 0 : void SAL_CALL ExportDocumentHandler::ignorableWhitespace(const OUString & aWhitespaces) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
287 : {
288 0 : m_xDelegatee->ignorableWhitespace(aWhitespaces);
289 0 : }
290 :
291 0 : void SAL_CALL ExportDocumentHandler::processingInstruction(const OUString & aTarget, const OUString & aData) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
292 : {
293 0 : m_xDelegatee->processingInstruction(aTarget,aData);
294 0 : }
295 :
296 0 : void SAL_CALL ExportDocumentHandler::setDocumentLocator(const uno::Reference< xml::sax::XLocator > & xLocator) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
297 : {
298 0 : m_xDelegatee->setDocumentLocator(xLocator);
299 0 : }
300 0 : void SAL_CALL ExportDocumentHandler::initialize( const uno::Sequence< uno::Any >& _aArguments ) throw (uno::Exception, uno::RuntimeException, std::exception)
301 : {
302 0 : ::osl::MutexGuard aGuard(m_aMutex);
303 0 : comphelper::SequenceAsHashMap aArgs(_aArguments);
304 0 : m_xDelegatee = aArgs.getUnpackedValueOrDefault("DocumentHandler",m_xDelegatee);
305 0 : m_xModel = aArgs.getUnpackedValueOrDefault("Model",m_xModel);
306 :
307 : OSL_ENSURE(m_xDelegatee.is(),"No document handler avialable!");
308 0 : if ( !m_xDelegatee.is() || !m_xModel.is() )
309 0 : throw uno::Exception();
310 :
311 0 : m_xDatabaseDataProvider.set(m_xModel->getDataProvider(),uno::UNO_QUERY);
312 0 : if ( !m_xDatabaseDataProvider.is() || !m_xDatabaseDataProvider->getActiveConnection().is() )
313 0 : throw uno::Exception();
314 :
315 0 : uno::Reference< reflection::XProxyFactory > xProxyFactory = reflection::ProxyFactory::create( m_xContext );
316 0 : m_xProxy = xProxyFactory->createProxy(m_xDelegatee.get());
317 0 : ::comphelper::query_aggregation(m_xProxy,m_xDelegatee);
318 0 : m_xTypeProvider.set(m_xDelegatee,uno::UNO_QUERY);
319 0 : m_xServiceInfo.set(m_xDelegatee,uno::UNO_QUERY);
320 :
321 : // set ourself as delegator
322 0 : m_xProxy->setDelegator( *this );
323 0 : const OUString sCommand = m_xDatabaseDataProvider->getCommand();
324 0 : if ( !sCommand.isEmpty() )
325 0 : m_aColumns = ::dbtools::getFieldNamesByCommandDescriptor(m_xDatabaseDataProvider->getActiveConnection()
326 0 : ,m_xDatabaseDataProvider->getCommandType()
327 0 : ,sCommand);
328 :
329 0 : uno::Reference< chart::XComplexDescriptionAccess > xDataProvider(m_xDatabaseDataProvider,uno::UNO_QUERY);
330 0 : if ( xDataProvider.is() )
331 : {
332 0 : m_aColumns.realloc(1);
333 0 : uno::Sequence< OUString > aColumnNames = xDataProvider->getColumnDescriptions();
334 0 : for(sal_Int32 i = 0 ; i < aColumnNames.getLength();++i)
335 : {
336 0 : if ( !aColumnNames[i].isEmpty() )
337 : {
338 0 : sal_Int32 nCount = m_aColumns.getLength();
339 0 : m_aColumns.realloc(nCount+1);
340 0 : m_aColumns[nCount] = aColumnNames[i];
341 : }
342 0 : }
343 0 : }
344 0 : }
345 :
346 0 : uno::Any SAL_CALL ExportDocumentHandler::queryInterface( const uno::Type& _rType ) throw (uno::RuntimeException, std::exception)
347 : {
348 0 : uno::Any aReturn = ExportDocumentHandler_BASE::queryInterface(_rType);
349 0 : return aReturn.hasValue() ? aReturn : (m_xProxy.is() ? m_xProxy->queryAggregation(_rType) : aReturn);
350 : }
351 :
352 0 : uno::Sequence< uno::Type > SAL_CALL ExportDocumentHandler::getTypes( ) throw (uno::RuntimeException, std::exception)
353 : {
354 0 : if ( m_xTypeProvider.is() )
355 : return ::comphelper::concatSequences(
356 : ExportDocumentHandler_BASE::getTypes(),
357 0 : m_xTypeProvider->getTypes()
358 0 : );
359 0 : return ExportDocumentHandler_BASE::getTypes();
360 : }
361 :
362 0 : void ExportDocumentHandler::exportTableRows()
363 : {
364 0 : const OUString sRow( lcl_createAttribute(XML_NP_TABLE, XML_TABLE_ROW) );
365 0 : m_xDelegatee->startElement(sRow,NULL);
366 :
367 0 : const OUString sValueType( lcl_createAttribute(XML_NP_OFFICE, XML_VALUE_TYPE) );
368 :
369 : static const char s_sFieldPrefix[] = "field:[";
370 : static const char s_sFieldPostfix[] = "]";
371 0 : const OUString sCell( lcl_createAttribute(XML_NP_TABLE, XML_TABLE_CELL) );
372 0 : const OUString sP( lcl_createAttribute(XML_NP_TEXT, XML_P) );
373 0 : const OUString sFtext(lcl_createAttribute(XML_NP_RPT,XML_FORMATTED_TEXT) );
374 0 : const OUString sRElement(lcl_createAttribute(XML_NP_RPT,XML_REPORT_ELEMENT) );
375 0 : const OUString sRComponent( lcl_createAttribute(XML_NP_RPT,XML_REPORT_COMPONENT) ) ;
376 0 : const OUString sFormulaAttrib( lcl_createAttribute(XML_NP_RPT,XML_FORMULA) );
377 : static const char s_sString[] = "string";
378 : static const char s_sFloat[] = "float";
379 :
380 0 : SvXMLAttributeList* pCellAtt = new SvXMLAttributeList();
381 0 : uno::Reference< xml::sax::XAttributeList > xCellAtt = pCellAtt;
382 0 : pCellAtt->AddAttribute(sValueType,s_sString);
383 :
384 0 : bool bRemoveString = true;
385 0 : OUString sFormula;
386 0 : const sal_Int32 nCount = m_aColumns.getLength();
387 0 : if ( m_nColumnCount > nCount )
388 : {
389 0 : const sal_Int32 nEmptyCellCount = m_nColumnCount - nCount;
390 0 : for(sal_Int32 i = 0; i < nEmptyCellCount ; ++i)
391 : {
392 0 : m_xDelegatee->startElement(sCell,xCellAtt);
393 0 : if ( bRemoveString )
394 : {
395 0 : bRemoveString = false;
396 0 : pCellAtt->RemoveAttribute(sValueType);
397 0 : pCellAtt->AddAttribute(sValueType,s_sFloat);
398 : }
399 0 : m_xDelegatee->startElement(sP,NULL);
400 0 : m_xDelegatee->endElement(sP);
401 0 : m_xDelegatee->endElement(sCell);
402 : }
403 : }
404 0 : for(sal_Int32 i = 0; i < nCount ; ++i)
405 : {
406 0 : sFormula = s_sFieldPrefix;
407 0 : sFormula += m_aColumns[i];
408 0 : sFormula += s_sFieldPostfix;
409 0 : SvXMLAttributeList* pList = new SvXMLAttributeList();
410 0 : uno::Reference< xml::sax::XAttributeList > xAttribs = pList;
411 0 : pList->AddAttribute(sFormulaAttrib,sFormula);
412 :
413 0 : m_xDelegatee->startElement(sCell,xCellAtt);
414 0 : if ( bRemoveString )
415 : {
416 0 : bRemoveString = false;
417 0 : pCellAtt->RemoveAttribute(sValueType);
418 0 : pCellAtt->AddAttribute(sValueType,s_sFloat);
419 : }
420 0 : m_xDelegatee->startElement(sP,NULL);
421 0 : m_xDelegatee->startElement(sFtext,xAttribs);
422 0 : m_xDelegatee->startElement(sRElement,NULL);
423 0 : m_xDelegatee->startElement(sRComponent,NULL);
424 :
425 0 : m_xDelegatee->endElement(sRComponent);
426 0 : m_xDelegatee->endElement(sRElement);
427 0 : m_xDelegatee->endElement(sFtext);
428 0 : m_xDelegatee->endElement(sP);
429 0 : m_xDelegatee->endElement(sCell);
430 0 : }
431 :
432 0 : m_xDelegatee->endElement(sRow);
433 0 : }
434 :
435 : } // namespace rptxml
436 :
437 :
438 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|