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