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 "xmlImportDocumentHandler.hxx"
21 : #include <com/sun/star/sdb/CommandType.hpp>
22 : #include <com/sun/star/chart2/data/DatabaseDataProvider.hpp>
23 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
24 : #include <com/sun/star/chart2/data/XDataSource.hpp>
25 : #include <com/sun/star/chart/XComplexDescriptionAccess.hpp>
26 : #include <com/sun/star/chart/ChartDataRowSource.hpp>
27 : #include <com/sun/star/reflection/ProxyFactory.hpp>
28 : #include <comphelper/sequenceashashmap.hxx>
29 : #include <comphelper/documentconstants.hxx>
30 : #include <comphelper/namedvaluecollection.hxx>
31 : #include <cppuhelper/supportsservice.hxx>
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/xmlnmspe.hxx>
38 :
39 : #include "xmlHelper.hxx"
40 : #include "xmlEnums.hxx"
41 : #include "xmlExportDocumentHandler.hxx"
42 :
43 : #include <connectivity/dbtools.hxx>
44 :
45 : namespace rptxml
46 : {
47 : using namespace ::com::sun::star;
48 : using namespace ::xmloff::token;
49 :
50 0 : ImportDocumentHandler::ImportDocumentHandler(uno::Reference< uno::XComponentContext > const & context)
51 : :m_bImportedChart( false )
52 0 : ,m_xContext(context)
53 : {
54 0 : }
55 :
56 0 : ImportDocumentHandler::~ImportDocumentHandler()
57 : {
58 0 : if ( m_xProxy.is() )
59 : {
60 0 : m_xProxy->setDelegator( NULL );
61 0 : m_xProxy.clear();
62 : }
63 0 : }
64 0 : IMPLEMENT_GET_IMPLEMENTATION_ID(ImportDocumentHandler)
65 0 : IMPLEMENT_FORWARD_REFCOUNT( ImportDocumentHandler, ImportDocumentHandler_BASE )
66 :
67 0 : OUString SAL_CALL ImportDocumentHandler::getImplementationName( ) throw(uno::RuntimeException, std::exception)
68 : {
69 0 : return getImplementationName_Static();
70 : }
71 :
72 0 : sal_Bool SAL_CALL ImportDocumentHandler::supportsService( const OUString& ServiceName ) throw(uno::RuntimeException, std::exception)
73 : {
74 0 : return cppu::supportsService(this, ServiceName);
75 : }
76 :
77 0 : uno::Sequence< OUString > SAL_CALL ImportDocumentHandler::getSupportedServiceNames( ) throw(uno::RuntimeException, std::exception)
78 : {
79 0 : uno::Sequence< OUString > aSupported;
80 0 : if ( m_xServiceInfo.is() )
81 0 : aSupported = m_xServiceInfo->getSupportedServiceNames();
82 0 : return ::comphelper::concatSequences(getSupportedServiceNames_static(),aSupported);
83 : }
84 :
85 7 : OUString ImportDocumentHandler::getImplementationName_Static( ) throw(uno::RuntimeException)
86 : {
87 7 : return OUString("com.sun.star.comp.report.ImportDocumentHandler");
88 : }
89 :
90 0 : uno::Sequence< OUString > ImportDocumentHandler::getSupportedServiceNames_static( ) throw(uno::RuntimeException)
91 : {
92 0 : uno::Sequence< OUString > aSupported(1);
93 0 : aSupported[0] = "com.sun.star.report.ImportDocumentHandler";
94 0 : return aSupported;
95 : }
96 :
97 :
98 0 : uno::Reference< uno::XInterface > SAL_CALL ImportDocumentHandler::create( const uno::Reference< uno::XComponentContext >& _rxContext )
99 : {
100 0 : return *(new ImportDocumentHandler( _rxContext ));
101 : }
102 : // xml::sax::XDocumentHandler:
103 0 : void SAL_CALL ImportDocumentHandler::startDocument() throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
104 : {
105 0 : m_xDelegatee->startDocument();
106 0 : }
107 :
108 0 : void SAL_CALL ImportDocumentHandler::endDocument() throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
109 : {
110 0 : m_xDelegatee->endDocument();
111 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver(m_xModel,uno::UNO_QUERY_THROW);
112 0 : if ( xReceiver.is() && m_bImportedChart )
113 : {
114 : // this fills the chart again
115 0 : ::comphelper::NamedValueCollection aArgs;
116 0 : aArgs.put( "CellRangeRepresentation", OUString("all") );
117 0 : aArgs.put( "FirstCellAsLabel", uno::makeAny( sal_True ) );
118 0 : aArgs.put( "DataRowSource", uno::makeAny( chart::ChartDataRowSource_COLUMNS ) );
119 :
120 0 : bool bHasCategories = false;
121 :
122 0 : uno::Reference< chart2::data::XDataSource > xDataSource(m_xModel, uno::UNO_QUERY);
123 0 : if( xDataSource.is())
124 : {
125 0 : uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(xDataSource->getDataSequences());
126 0 : const sal_Int32 nCount( aSequences.getLength());
127 0 : for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
128 : {
129 0 : if( aSequences[nIdx].is() )
130 : {
131 0 : uno::Reference< beans::XPropertySet > xSeqProp( aSequences[nIdx]->getValues(), uno::UNO_QUERY );
132 0 : OUString aRole;
133 0 : if ( xSeqProp.is()
134 0 : && ( xSeqProp->getPropertyValue( "Role" ) >>= aRole )
135 0 : && aRole == "categories"
136 : )
137 : {
138 0 : bHasCategories = true;
139 0 : break;
140 0 : }
141 : }
142 0 : }
143 : }
144 0 : aArgs.put( "HasCategories", uno::makeAny( bHasCategories ) );
145 :
146 0 : uno::Reference< chart::XComplexDescriptionAccess > xDataProvider(m_xModel->getDataProvider(),uno::UNO_QUERY);
147 0 : if ( xDataProvider.is() )
148 : {
149 0 : const uno::Sequence< OUString > aColumnNames = xDataProvider->getColumnDescriptions();
150 0 : aArgs.put( "ColumnDescriptions", uno::makeAny( aColumnNames ) );
151 : }
152 :
153 0 : xReceiver->attachDataProvider( m_xDatabaseDataProvider.get() );
154 0 : xReceiver->setArguments( aArgs.getPropertyValues() );
155 0 : }
156 0 : }
157 :
158 0 : void SAL_CALL ImportDocumentHandler::startElement(const OUString & _sName, const uno::Reference< xml::sax::XAttributeList > & _xAttrList) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
159 : {
160 0 : uno::Reference< xml::sax::XAttributeList > xNewAttribs = _xAttrList;
161 0 : bool bExport = true;
162 0 : if ( _sName == "office:report" )
163 : {
164 0 : const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
165 0 : static const OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
166 : try
167 : {
168 0 : for(sal_Int16 i = 0; i < nLength; ++i)
169 : {
170 0 : OUString sLocalName;
171 0 : const OUString sAttrName = _xAttrList->getNameByIndex( i );
172 0 : const sal_Int32 nColonPos = sAttrName.indexOf( ':' );
173 0 : if( -1L == nColonPos )
174 0 : sLocalName = sAttrName;
175 : else
176 0 : sLocalName = sAttrName.copy( nColonPos + 1L );
177 0 : const OUString sValue = _xAttrList->getValueByIndex( i );
178 :
179 0 : switch( m_pReportElemTokenMap->Get( XML_NAMESPACE_REPORT, sLocalName ) )
180 : {
181 : case XML_TOK_COMMAND_TYPE:
182 : {
183 0 : sal_uInt16 nRet = static_cast<sal_uInt16>(sdb::CommandType::COMMAND);
184 0 : const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetCommandTypeOptions();
185 0 : (void)SvXMLUnitConverter::convertEnum( nRet, sValue, aXML_EnumMap );
186 0 : m_xDatabaseDataProvider->setCommandType(nRet);
187 : }
188 0 : break;
189 : case XML_TOK_COMMAND:
190 0 : m_xDatabaseDataProvider->setCommand(sValue);
191 0 : break;
192 : case XML_TOK_FILTER:
193 0 : m_xDatabaseDataProvider->setFilter(sValue);
194 0 : break;
195 : case XML_TOK_ESCAPE_PROCESSING:
196 0 : m_xDatabaseDataProvider->setEscapeProcessing(sValue == s_sTRUE);
197 0 : break;
198 : default:
199 0 : break;
200 : }
201 0 : }
202 : }
203 0 : catch(uno::Exception&)
204 : {
205 : }
206 0 : m_xDelegatee->startElement(lcl_createAttribute(XML_NP_OFFICE,XML_CHART),NULL);
207 0 : bExport = false;
208 0 : m_bImportedChart = true;
209 : }
210 0 : else if ( _sName == "rpt:master-detail-field" )
211 : {
212 0 : const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
213 0 : ::std::unique_ptr<SvXMLTokenMap> pMasterElemTokenMap( OXMLHelper::GetSubDocumentElemTokenMap());
214 : try
215 : {
216 0 : OUString sMasterField,sDetailField;
217 0 : for(sal_Int16 i = 0; i < nLength; ++i)
218 : {
219 0 : OUString sLocalName;
220 0 : const OUString sAttrName = _xAttrList->getNameByIndex( i );
221 0 : const sal_Int32 nColonPos = sAttrName.indexOf( ':' );
222 0 : if( -1L == nColonPos )
223 0 : sLocalName = sAttrName;
224 : else
225 0 : sLocalName = sAttrName.copy( nColonPos + 1L );
226 0 : const OUString sValue = _xAttrList->getValueByIndex( i );
227 :
228 0 : switch( pMasterElemTokenMap->Get( XML_NAMESPACE_REPORT, sLocalName ) )
229 : {
230 : case XML_TOK_MASTER:
231 0 : sMasterField = sValue;
232 0 : break;
233 : case XML_TOK_SUB_DETAIL:
234 0 : sDetailField = sValue;
235 0 : break;
236 : }
237 0 : }
238 0 : if ( sDetailField.isEmpty() )
239 0 : sDetailField = sMasterField;
240 0 : m_aMasterFields.push_back(sMasterField);
241 0 : m_aDetailFields.push_back(sDetailField);
242 : }
243 0 : catch(uno::Exception&)
244 : {
245 : OSL_FAIL("Exception catched while filling the report definition props");
246 : }
247 0 : bExport = false;
248 : }
249 0 : else if ( _sName == "rpt:detail"
250 0 : || _sName == "rpt:formatted-text"
251 0 : || _sName == "rpt:master-detail-fields"
252 0 : || _sName == "rpt:report-component"
253 0 : || _sName == "rpt:report-element")
254 0 : bExport = false;
255 0 : else if ( _sName == "chart:plot-area" )
256 : {
257 0 : bool bHasCategories = true;
258 0 : const sal_Int16 nLength = (_xAttrList.is()) ? _xAttrList->getLength() : 0;
259 0 : ::std::unique_ptr<SvXMLTokenMap> pMasterElemTokenMap( OXMLHelper::GetSubDocumentElemTokenMap());
260 0 : for(sal_Int16 i = 0; i < nLength; ++i)
261 : {
262 0 : OUString sLocalName;
263 0 : const OUString sAttrName = _xAttrList->getNameByIndex( i );
264 0 : const sal_Int32 nColonPos = sAttrName.indexOf( ':' );
265 0 : if( -1L == nColonPos )
266 0 : sLocalName = sAttrName;
267 : else
268 0 : sLocalName = sAttrName.copy( nColonPos + 1L );
269 0 : if ( sLocalName == "data-source-has-labels" )
270 : {
271 0 : const OUString sValue = _xAttrList->getValueByIndex( i );
272 0 : bHasCategories = sValue == "both";
273 0 : break;
274 : }
275 0 : }
276 0 : beans::PropertyValue* pArgIter = m_aArguments.getArray();
277 0 : beans::PropertyValue* pArgEnd = pArgIter + m_aArguments.getLength();
278 0 : for(;pArgIter != pArgEnd;++pArgIter)
279 : {
280 0 : if ( pArgIter->Name == "HasCategories" )
281 : {
282 0 : pArgIter->Value <<= bHasCategories;
283 0 : break;
284 : }
285 : }
286 :
287 0 : SvXMLAttributeList* pList = new SvXMLAttributeList();
288 0 : xNewAttribs = pList;
289 0 : pList->AppendAttributeList(_xAttrList);
290 0 : pList->AddAttribute(OUString("table:cell-range-address"),OUString("local-table.$A$1:.$Z$65536"));
291 :
292 : }
293 :
294 0 : if ( bExport )
295 0 : m_xDelegatee->startElement(_sName,xNewAttribs);
296 0 : }
297 :
298 0 : void SAL_CALL ImportDocumentHandler::endElement(const OUString & _sName) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
299 : {
300 0 : bool bExport = true;
301 0 : OUString sNewName = _sName;
302 0 : if ( _sName == "office:report" )
303 : {
304 0 : sNewName = lcl_createAttribute(XML_NP_OFFICE,XML_CHART);
305 : }
306 0 : else if ( _sName == "rpt:master-detail-fields" )
307 : {
308 0 : if ( !m_aMasterFields.empty() )
309 0 : m_xDatabaseDataProvider->setMasterFields(uno::Sequence< OUString>(&*m_aMasterFields.begin(),m_aMasterFields.size()));
310 0 : if ( !m_aDetailFields.empty() )
311 0 : m_xDatabaseDataProvider->setDetailFields(uno::Sequence< OUString>(&*m_aDetailFields.begin(),m_aDetailFields.size()));
312 0 : bExport = false;
313 : }
314 0 : else if ( _sName == "rpt:detail"
315 0 : || _sName == "rpt:formatted-text"
316 0 : || _sName == "rpt:master-detail-field"
317 0 : || _sName == "rpt:report-component"
318 0 : || _sName == "rpt:report-element")
319 0 : bExport = false;
320 :
321 0 : if ( bExport )
322 0 : m_xDelegatee->endElement(sNewName);
323 0 : }
324 :
325 0 : void SAL_CALL ImportDocumentHandler::characters(const OUString & aChars) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
326 : {
327 0 : m_xDelegatee->characters(aChars);
328 0 : }
329 :
330 0 : void SAL_CALL ImportDocumentHandler::ignorableWhitespace(const OUString & aWhitespaces) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
331 : {
332 0 : m_xDelegatee->ignorableWhitespace(aWhitespaces);
333 0 : }
334 :
335 0 : void SAL_CALL ImportDocumentHandler::processingInstruction(const OUString & aTarget, const OUString & aData) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
336 : {
337 0 : m_xDelegatee->processingInstruction(aTarget,aData);
338 0 : }
339 :
340 0 : void SAL_CALL ImportDocumentHandler::setDocumentLocator(const uno::Reference< xml::sax::XLocator > & xLocator) throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
341 : {
342 0 : m_xDelegatee->setDocumentLocator(xLocator);
343 0 : }
344 0 : void SAL_CALL ImportDocumentHandler::initialize( const uno::Sequence< uno::Any >& _aArguments ) throw (uno::Exception, uno::RuntimeException, std::exception)
345 : {
346 0 : ::osl::MutexGuard aGuard(m_aMutex);
347 0 : comphelper::SequenceAsHashMap aArgs(_aArguments);
348 0 : m_xDelegatee = aArgs.getUnpackedValueOrDefault("DocumentHandler",m_xDelegatee);
349 0 : m_xModel = aArgs.getUnpackedValueOrDefault("Model",m_xModel);
350 :
351 : OSL_ENSURE(m_xDelegatee.is(),"No document handler avialable!");
352 0 : if ( !m_xDelegatee.is() || !m_xModel.is() )
353 0 : throw uno::Exception();
354 :
355 0 : m_xDatabaseDataProvider.set(m_xModel->getDataProvider(),uno::UNO_QUERY);
356 0 : if ( !m_xDatabaseDataProvider.is() )
357 : {
358 : static const char s_sDatabaseDataProvider[] = "com.sun.star.chart2.data.DatabaseDataProvider";
359 0 : m_xDatabaseDataProvider.set(m_xContext->getServiceManager()->createInstanceWithContext(s_sDatabaseDataProvider
360 0 : ,m_xContext),uno::UNO_QUERY);
361 0 : if ( !m_xDatabaseDataProvider.is() )
362 0 : throw uno::Exception();
363 :
364 0 : m_xDatabaseDataProvider->setRowLimit(10);
365 :
366 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver(m_xModel,uno::UNO_QUERY_THROW);
367 0 : xReceiver->attachDataProvider(m_xDatabaseDataProvider.get());
368 : }
369 :
370 0 : m_aArguments = m_xDatabaseDataProvider->detectArguments(NULL);
371 :
372 0 : uno::Reference< reflection::XProxyFactory > xProxyFactory = reflection::ProxyFactory::create( m_xContext );
373 0 : m_xProxy = xProxyFactory->createProxy(m_xDelegatee.get());
374 0 : ::comphelper::query_aggregation(m_xProxy,m_xDelegatee);
375 0 : m_xTypeProvider.set(m_xDelegatee,uno::UNO_QUERY);
376 0 : m_xServiceInfo.set(m_xDelegatee,uno::UNO_QUERY);
377 :
378 : // set ourself as delegator
379 0 : m_xProxy->setDelegator( *this );
380 :
381 0 : m_pReportElemTokenMap.reset(OXMLHelper::GetReportElemTokenMap());
382 0 : }
383 :
384 0 : uno::Any SAL_CALL ImportDocumentHandler::queryInterface( const uno::Type& _rType ) throw (uno::RuntimeException, std::exception)
385 : {
386 0 : uno::Any aReturn = ImportDocumentHandler_BASE::queryInterface(_rType);
387 0 : return aReturn.hasValue() ? aReturn : (m_xProxy.is() ? m_xProxy->queryAggregation(_rType) : aReturn);
388 : }
389 :
390 0 : uno::Sequence< uno::Type > SAL_CALL ImportDocumentHandler::getTypes( ) throw (uno::RuntimeException, std::exception)
391 : {
392 0 : if ( m_xTypeProvider.is() )
393 : return ::comphelper::concatSequences(
394 : ImportDocumentHandler_BASE::getTypes(),
395 0 : m_xTypeProvider->getTypes()
396 0 : );
397 0 : return ImportDocumentHandler_BASE::getTypes();
398 : }
399 :
400 :
401 : } // namespace rptxml
402 :
403 :
404 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|