LibreOffice Module xmloff (master) 1
SchXMLImport.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 <SchXMLImport.hxx>
22#include "contexts.hxx"
23#include "SchXMLTools.hxx"
24
25#include <sal/log.hxx>
27#include <utility>
29#include <xmloff/prstylei.hxx>
31#include <xmloff/xmltoken.hxx>
32#include <xmloff/xmluconv.hxx>
33#include <xmloff/xmlictxt.hxx>
34#include <xmloff/xmlstyle.hxx>
35#include <com/sun/star/chart/XChartDocument.hpp>
36#include <com/sun/star/container/XChild.hpp>
37#include <com/sun/star/lang/XMultiServiceFactory.hpp>
38#include <com/sun/star/uno/XComponentContext.hpp>
39#include <com/sun/star/chart2/data/XDataReceiver.hpp>
40#include <com/sun/star/chart2/XChartDocument.hpp>
41#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
42#include <com/sun/star/chart2/XChartTypeContainer.hpp>
43#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
44
45#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
46
48
49using namespace com::sun::star;
50using namespace ::xmloff::token;
51
52using ::com::sun::star::uno::Reference;
53using ::com::sun::star::uno::Sequence;
54
55namespace
56{
57class lcl_MatchesChartType
58{
59public:
60 explicit lcl_MatchesChartType( OUString aChartTypeName ) :
61 m_aChartTypeName(std::move( aChartTypeName ))
62 {}
63
64 bool operator () ( const Reference< chart2::XChartType > & xChartType ) const
65 {
66 return (xChartType.is() &&
67 xChartType->getChartType() == m_aChartTypeName );
68 }
69
70private:
71 OUString m_aChartTypeName;
72};
73} // anonymous namespace
74
75 // TokenMaps for distinguishing different
76 // tokens in different contexts
77
78// element maps
79
80// attribute maps
81
83 mpAutoStyles( nullptr )
84{
85}
86
88 SvXMLImport& rImport,
89 const Reference< frame::XModel >& rChartModel )
90{
91 SvXMLImportContext* pContext = nullptr;
92
93 Reference< chart::XChartDocument > xDoc( rChartModel, uno::UNO_QUERY );
94 if( xDoc.is())
95 {
96 mxChartDoc = xDoc;
97 pContext = new SchXMLChartContext( *this, rImport );
98 }
99 else
100 {
101 SAL_WARN("xmloff.chart", "No valid XChartDocument given as XModel" );
102 }
103
104 return pContext;
105}
106
107void SchXMLImportHelper::FillAutoStyle(const OUString& rAutoStyleName, const uno::Reference<beans::XPropertySet>& rProp)
108{
109 if (!rProp.is())
110 return;
111
112 const SvXMLStylesContext* pStylesCtxt = GetAutoStylesContext();
113 if (pStylesCtxt)
114 {
115 SvXMLStyleContext* pStyle = const_cast<SvXMLStyleContext*>(pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(), rAutoStyleName));
116
117 if (XMLPropStyleContext* pPropStyle = dynamic_cast<XMLPropStyleContext*>(pStyle))
118 pPropStyle->FillPropertySet(rProp);
119 }
120}
121
122// get various token maps
123
124
125//static
127 const Reference< chart2::XDataSeries > & xSeries,
128 const Reference< chart2::XChartDocument > & xDoc )
129{
130 if( !xDoc.is() )
131 return;
132 try
133 {
134 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
135 xDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
136 const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
137 xCooSysCnt->getCoordinateSystems());
138
139 for( const auto& rCooSys : aCooSysSeq )
140 {
141 Reference< chart2::XChartTypeContainer > xCTCnt( rCooSys, uno::UNO_QUERY_THROW );
142 const Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
143
144 for( const auto& rChartType : aChartTypes )
145 {
146 Reference< chart2::XDataSeriesContainer > xSeriesCnt( rChartType, uno::UNO_QUERY_THROW );
147 const Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesCnt->getDataSeries());
148
149 if (std::find(aSeriesSeq.begin(), aSeriesSeq.end(), xSeries) != aSeriesSeq.end())
150 {
151 xSeriesCnt->removeDataSeries(xSeries);
152 return;
153 }
154 }
155 }
156 }
157 catch( const uno::Exception &)
158 {
159 DBG_UNHANDLED_EXCEPTION("xmloff.chart");
160 }
161}
162
163// static
164Reference< chart2::XDataSeries > SchXMLImportHelper::GetNewDataSeries(
165 const Reference< chart2::XChartDocument > & xDoc,
166 sal_Int32 nCoordinateSystemIndex,
167 const OUString & rChartTypeName,
168 bool bPushLastChartType /* = false */ )
169{
170 Reference< chart2::XDataSeries > xResult;
171 if(!xDoc.is())
172 return xResult;
173
174 try
175 {
176 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
177 xDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
178 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
179 xCooSysCnt->getCoordinateSystems());
180 Reference< uno::XComponentContext > xContext(
182
183 if( nCoordinateSystemIndex < aCooSysSeq.getLength())
184 {
185 Reference< chart2::XChartType > xCurrentType;
186 {
187 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[ nCoordinateSystemIndex ], uno::UNO_QUERY_THROW );
188 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
189 // find matching chart type group
190 const Reference< chart2::XChartType > * pBegin = aChartTypes.getConstArray();
191 const Reference< chart2::XChartType > * pEnd = pBegin + aChartTypes.getLength();
192 const Reference< chart2::XChartType > * pIt =
193 ::std::find_if( pBegin, pEnd, lcl_MatchesChartType( rChartTypeName ));
194 if( pIt != pEnd )
195 xCurrentType.set( *pIt );
196 // if chart type is set at series and differs from current one,
197 // create a new chart type
198 if( !xCurrentType.is())
199 {
200 xCurrentType.set(
201 xContext->getServiceManager()->createInstanceWithContext( rChartTypeName, xContext ),
202 uno::UNO_QUERY );
203 if( xCurrentType.is())
204 {
205 if( bPushLastChartType && aChartTypes.hasElements())
206 {
207 sal_Int32 nIndex( aChartTypes.getLength() - 1 );
208 aChartTypes.realloc( aChartTypes.getLength() + 1 );
209 auto pChartTypes = aChartTypes.getArray();
210 pChartTypes[ nIndex + 1 ] = aChartTypes[ nIndex ];
211 pChartTypes[ nIndex ] = xCurrentType;
212 xCTCnt->setChartTypes( aChartTypes );
213 }
214 else
215 xCTCnt->addChartType( xCurrentType );
216 }
217 }
218 }
219
220 if( xCurrentType.is())
221 {
222 Reference< chart2::XDataSeriesContainer > xSeriesCnt( xCurrentType, uno::UNO_QUERY_THROW );
223
224 if( xContext.is() )
225 {
226 xResult.set(
227 xContext->getServiceManager()->createInstanceWithContext(
228 "com.sun.star.chart2.DataSeries",
229 xContext ), uno::UNO_QUERY_THROW );
230 }
231 if( xResult.is() )
232 xSeriesCnt->addDataSeries( xResult );
233 }
234 }
235 }
236 catch( const uno::Exception & )
237 {
238 DBG_UNHANDLED_EXCEPTION("xmloff.chart");
239 }
240 return xResult;
241}
242
244 const Reference< uno::XComponentContext >& xContext,
245 OUString const & implementationName, SvXMLImportFlags nImportFlags ) :
246 SvXMLImport( xContext, implementationName, nImportFlags ),
247 maImportHelper(new SchXMLImportHelper)
248{
251}
252
254{
255 uno::Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
256 if( xChartDoc.is() && xChartDoc->hasControllersLocked() )
257 xChartDoc->unlockControllers();
258}
259
260// create the main context (subcontexts are created
261// by the one created here)
263 const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
264{
265 SvXMLImportContext* pContext = nullptr;
266
267 switch (nElement)
268 {
271 {
272 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
273 GetModel(), uno::UNO_QUERY);
274 // mst@: right now, this seems to be not supported, so it is untested
275 if (xDPS.is()) {
276 pContext = (nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT_META))
277 ? new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties())
278 // flat OpenDocument file format
279 : new SchXMLFlatDocContext_Impl(*maImportHelper, *this, nElement,
280 xDPS->getDocumentProperties());
281 }
282 }
283 break;
284 // accept <office:document>
287 pContext = new SchXMLDocContext(*maImportHelper, *this, nElement);
288 break;
289 }
290 return pContext;
291}
292
294{
295 //#i103287# make sure that the version information is set before importing all the properties (especially stroke-opacity!)
296 SchXMLTools::setBuildIDAtImportInfo( GetModel(), getImportInfo() );
297
298 SvXMLStylesContext* pStylesCtxt = new SvXMLStylesContext( *this );
299
300 // set context at base class, so that all auto-style classes are imported
301 SetAutoStyles( pStylesCtxt );
302 maImportHelper->SetAutoStylesContext( pStylesCtxt );
303
304 return pStylesCtxt;
305}
306
307void SAL_CALL SchXMLImport::setTargetDocument(const uno::Reference<lang::XComponent>& xDoc)
308{
309 uno::Reference<chart2::XChartDocument> xOldDoc(GetModel(), uno::UNO_QUERY);
310 if (xOldDoc.is() && xOldDoc->hasControllersLocked())
311 xOldDoc->unlockControllers();
312
313 SvXMLImport::setTargetDocument(xDoc);
314
315 uno::Reference<chart2::XChartDocument> xChartDoc(GetModel(), uno::UNO_QUERY);
316
317 if (!xChartDoc.is())
318 return;
319 try
320 {
321 // prevent rebuild of view during load (necessary especially if loaded not
322 // via load api, which is the case for example if binary files are loaded)
323 xChartDoc->lockControllers();
324
325 uno::Reference<container::XChild> xChild(xChartDoc, uno::UNO_QUERY);
326 uno::Reference<chart2::data::XDataReceiver> xDataReceiver(xChartDoc, uno::UNO_QUERY);
327 if (xChild.is() && xDataReceiver.is())
328 {
329 Reference<lang::XMultiServiceFactory> xFact(xChild->getParent(), uno::UNO_QUERY);
330 if (xFact.is())
331 {
332 //if the parent has a number formatter we will use the numberformatter of the parent
333 Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(xFact, uno::UNO_QUERY);
334 xDataReceiver->attachNumberFormatsSupplier(xNumberFormatsSupplier);
335 }
336 }
337 }
338 catch (const uno::Exception &)
339 {
340 TOOLS_INFO_EXCEPTION("xmloff.chart", "SchXMLChartContext::StartElement(): Exception caught");
341 }
342}
343
344// first version: everything comes from one storage
345
346extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
348 uno::Sequence<uno::Any> const& /*rSeq*/)
349{
350 return cppu::acquire(new SchXMLImport(pCtx, "SchXMLImport", SvXMLImportFlags::ALL));
351}
352
353// multiple storage version: one for content / styles / meta
354
355extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
357 uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
358{
359 return cppu::acquire(new SchXMLImport(pCtx, "SchXMLImport.Meta", SvXMLImportFlags::META));
360}
361
362extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
364 uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
365{
366 return cppu::acquire(new SchXMLImport(pCtx, "SchXMLImport.Styles", SvXMLImportFlags::STYLES));
367}
368
369extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
371 uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
372{
373 return cppu::acquire(new SchXMLImport(pCtx, "SchXMLImport.Content",
376}
377
378/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisContentImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisMetaImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisStylesImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
With this class you can import a <chart:chart> element containing its data as <table:table> element o...
static void DeleteDataSeries(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const css::uno::Reference< css::chart2::XChartDocument > &xDoc)
css::uno::Reference< css::chart::XChartDocument > mxChartDoc
SvXMLStylesContext * GetAutoStylesContext() const
SvXMLImportContext * CreateChartContext(SvXMLImport &rImport, const css::uno::Reference< css::frame::XModel > &rChartModel)
get the context for reading the <chart:chart> element with subelements.
void FillAutoStyle(const OUString &rAutoStyleName, const css::uno::Reference< css::beans::XPropertySet > &rProp)
Fill in the autostyle.
static css::uno::Reference< css::chart2::XDataSeries > GetNewDataSeries(const css::uno::Reference< css::chart2::XChartDocument > &xDoc, sal_Int32 nCoordinateSystemIndex, const OUString &rChartTypeName, bool bPushLastChartType)
static XmlStyleFamily GetChartFamilyID()
virtual ~SchXMLImport() noexcept override
virtual void SAL_CALL setTargetDocument(const css::uno::Reference< css::lang::XComponent > &xDoc) override
rtl::Reference< SchXMLImportHelper > maImportHelper
virtual SvXMLImportContext * CreateFastContext(sal_Int32 nElement, const ::css::uno::Reference<::css::xml::sax::XFastAttributeList > &xAttrList) override
SvXMLImportContext * CreateStylesContext()
SchXMLImport(const css::uno::Reference< css::uno::XComponentContext > &xContext, OUString const &implementationName, SvXMLImportFlags nImportFlags)
This class deliberately does not support XWeak, to improve performance when loading large documents.
Definition: xmlictxt.hxx:48
handles the top-level office:document-meta element of meta.xml documents
Definition: xmlmetai.hxx:37
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:783
#define TOOLS_INFO_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
sal_Int32 nIndex
#define SAL_WARN(area, stream)
void setBuildIDAtImportInfo(const uno::Reference< frame::XModel > &xModel, const Reference< beans::XPropertySet > &xImportInfo)
Reference< XComponentContext > getProcessComponentContext()
constexpr OUStringLiteral implementationName
Handling of tokens in XML:
@ XML_DOCUMENT_CONTENT
Definition: xmltoken.hxx:702
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3541
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
SvXMLImportFlags
Definition: xmlimp.hxx:111
constexpr sal_uInt16 XML_NAMESPACE_XLINK
constexpr sal_uInt16 XML_NAMESPACE_CHART_EXT