update dev300-m58
[ooovba.git] / xmloff / source / chart / SchXMLTools.cxx
blob40828bf400d0c73f0bfd09848822d41fb65fd65e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SchXMLTools.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
34 #include "SchXMLTools.hxx"
37 #include <tools/debug.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <comphelper/InlineContainer.hxx>
41 // header for class SvXMLUnitConverter
42 #include <xmloff/xmluconv.hxx>
43 // header for struct SvXMLEnumMapEntry
44 #include <xmloff/xmlement.hxx>
45 // header for define __FAR_DATA
46 #include <tools/solar.h>
48 // header for class SvXMLImportPropertyMapper
49 #include <xmloff/xmlimppr.hxx>
50 // header for class XMLPropStyleContext
51 #include <xmloff/prstylei.hxx>
52 // header for class XMLPropertySetMapper
53 #include <xmloff/xmlprmap.hxx>
54 #include <xmloff/xmlexp.hxx>
55 #include "xmlnmspe.hxx"
56 #include <xmloff/xmlmetai.hxx>
58 #include <com/sun/star/beans/PropertyAttribute.hpp>
59 #include <com/sun/star/uno/XComponentContext.hpp>
60 #include <com/sun/star/chart2/data/XDataProvider.hpp>
61 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
62 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
63 #include <com/sun/star/chart2/XChartDocument.hpp>
64 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
65 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
66 #include <com/sun/star/container/XChild.hpp>
67 #include <com/sun/star/document/XDocumentProperties.hpp>
68 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
69 #include <com/sun/star/lang/XServiceName.hpp>
71 #include <comphelper/processfactory.hxx>
73 using namespace com::sun::star;
74 using namespace ::xmloff::token;
76 using ::rtl::OUString;
77 using ::rtl::OUStringBuffer;
78 using ::com::sun::star::uno::Reference;
79 using ::com::sun::star::uno::Sequence;
81 namespace
83 Reference< uno::XComponentContext > lcl_getComponentContext()
85 Reference< uno::XComponentContext > xContext;
86 try
88 Reference< beans::XPropertySet > xFactProp( comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
89 if( xFactProp.is())
90 xFactProp->getPropertyValue(OUString::createFromAscii("DefaultContext")) >>= xContext;
92 catch( uno::Exception& )
95 return xContext;
98 rtl::OUString lcl_getGeneratorFromModel( const uno::Reference< frame::XModel >& xChartModel )
100 ::rtl::OUString aGenerator;
101 uno::Reference< document::XDocumentPropertiesSupplier> xChartDocumentPropertiesSupplier( xChartModel, uno::UNO_QUERY );
102 if( xChartDocumentPropertiesSupplier.is() )
104 uno::Reference< document::XDocumentProperties > xChartDocumentProperties(
105 xChartDocumentPropertiesSupplier->getDocumentProperties());
106 if( xChartDocumentProperties.is() )
107 aGenerator = xChartDocumentProperties->getGenerator();
109 return aGenerator;
112 rtl::OUString lcl_getGeneratorFromModelOrItsParent( const uno::Reference< frame::XModel >& xChartModel )
114 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
115 if( !aGenerator.getLength() ) //try to get the missing info from the parent document
117 uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
118 if( xChild.is() )
119 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
121 return aGenerator;
124 sal_Int32 lcl_getBuildIDFromGenerator( const ::rtl::OUString& rGenerator )
126 //returns -1 if nothing found
127 sal_Int32 nBuildId = -1;
128 const OUString sBuildCompare( RTL_CONSTASCII_USTRINGPARAM( "$Build-" ) );
129 sal_Int32 nEnd = -1;
130 sal_Int32 nBegin = rGenerator.indexOf( sBuildCompare, nEnd );
131 if( nBegin != -1 )
133 OUString sBuildId( rGenerator.copy( nBegin + sBuildCompare.getLength() ) );
134 nBuildId = sBuildId.toInt32();
136 return nBuildId;
139 Reference< chart2::data::XDataSequence > lcl_createNewSequenceFromCachedXMLRange( const Reference< chart2::data::XDataSequence >& xSeq, const Reference< chart2::data::XDataProvider >& xDataProvider )
141 Reference< chart2::data::XDataSequence > xRet;
142 OUString aRange;
143 Reference< chart2::data::XRangeXMLConversion > xRangeConversion( xDataProvider, uno::UNO_QUERY );
144 if( xRangeConversion.is() )
146 if( xSeq.is() && SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) )
148 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation(
149 xRangeConversion->convertRangeFromXML( aRange )) );
150 SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
151 Reference< beans::XPropertySet >( xRet, uno::UNO_QUERY ));
154 return xRet;
157 } // anonymous namespace
159 // ----------------------------------------
161 namespace SchXMLTools
164 static __FAR_DATA SvXMLEnumMapEntry aXMLChartClassMap[] =
166 { XML_LINE, XML_CHART_CLASS_LINE },
167 { XML_AREA, XML_CHART_CLASS_AREA },
168 { XML_CIRCLE, XML_CHART_CLASS_CIRCLE },
169 { XML_RING, XML_CHART_CLASS_RING },
170 { XML_SCATTER, XML_CHART_CLASS_SCATTER },
171 { XML_RADAR, XML_CHART_CLASS_RADAR },
172 { XML_FILLED_RADAR, XML_CHART_CLASS_FILLED_RADAR },
173 { XML_BAR, XML_CHART_CLASS_BAR },
174 { XML_STOCK, XML_CHART_CLASS_STOCK },
175 { XML_BUBBLE, XML_CHART_CLASS_BUBBLE },
176 { XML_ADD_IN, XML_CHART_CLASS_ADDIN },
177 { XML_TOKEN_INVALID, XML_CHART_CLASS_UNKNOWN }
180 SchXMLChartTypeEnum GetChartTypeEnum( const OUString& rClassName )
182 USHORT nEnumVal = XML_CHART_CLASS_UNKNOWN;
183 if( !SvXMLUnitConverter::convertEnum(
184 nEnumVal, rClassName, aXMLChartClassMap ) )
185 nEnumVal = XML_CHART_CLASS_UNKNOWN;
186 return SchXMLChartTypeEnum(nEnumVal);
189 typedef ::comphelper::MakeMap< ::rtl::OUString, ::rtl::OUString > tMakeStringStringMap;
190 //static
191 const tMakeStringStringMap& lcl_getChartTypeNameMap()
193 //shape property -- chart model object property
194 static tMakeStringStringMap g_aChartTypeNameMap =
195 tMakeStringStringMap
196 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.LineDiagram" )
197 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.LineChartType" ) )
199 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.AreaDiagram" )
200 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.AreaChartType" ) )
202 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.BarDiagram" )
203 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.ColumnChartType" ) )
205 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.PieDiagram" )
206 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.PieChartType" ) )
208 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.DonutDiagram" )
209 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.DonutChartType" ) )
211 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.XYDiagram" )
212 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.ScatterChartType" ) )
214 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.NetDiagram" )
215 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.NetChartType" ) )
217 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.FilledNetDiagram" )
218 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.FilledNetChartType" ) )
220 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.StockDiagram" )
221 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.CandleStickChartType" ) )
223 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.BubbleDiagram" )
224 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.BubbleChartType" ) )
227 return g_aChartTypeNameMap;
231 OUString GetNewChartTypeName( const OUString & rOldChartTypeName )
233 OUString aNew(rOldChartTypeName);
235 const tMakeStringStringMap& rMap = lcl_getChartTypeNameMap();
236 tMakeStringStringMap::const_iterator aIt( rMap.find( rOldChartTypeName ));
237 if( aIt != rMap.end())
239 aNew = aIt->second;
241 return aNew;
244 OUString GetChartTypeByClassName(
245 const OUString & rClassName, bool bUseOldNames )
247 OUStringBuffer aResultBuffer;
248 bool bInternalType = false;
250 if( bUseOldNames )
251 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart."));
252 else
253 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2."));
255 bInternalType = true;
257 if( IsXMLToken( rClassName, XML_LINE ))
258 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Line"));
259 else if( IsXMLToken( rClassName, XML_AREA ))
260 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Area"));
261 else if( IsXMLToken( rClassName, XML_BAR ))
263 if( bUseOldNames )
264 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Bar"));
265 else
267 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Column"));
268 // @todo: might be Bar
271 else if( IsXMLToken( rClassName, XML_CIRCLE ))
272 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Pie"));
273 else if( IsXMLToken( rClassName, XML_RING ))
274 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Donut"));
275 else if( IsXMLToken( rClassName, XML_SCATTER ))
277 if( bUseOldNames )
278 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("XY"));
279 else
280 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Scatter"));
283 else if( IsXMLToken( rClassName, XML_BUBBLE ))
284 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Bubble"));
285 else if( IsXMLToken( rClassName, XML_RADAR ))
286 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Net"));
287 else if( IsXMLToken( rClassName, XML_FILLED_RADAR ))
288 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("FilledNet"));
289 else if( IsXMLToken( rClassName, XML_STOCK ))
291 if( bUseOldNames )
292 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Stock"));
293 else
294 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("CandleStick"));
296 else
297 bInternalType = false;
299 if( ! bInternalType )
300 return OUString();
302 if( bUseOldNames )
303 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Diagram"));
304 else
305 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("ChartType"));
307 return aResultBuffer.makeStringAndClear();
311 XMLTokenEnum getTokenByChartType(
312 const OUString & rChartTypeService, bool bUseOldNames )
314 XMLTokenEnum eResult = XML_TOKEN_INVALID;
315 OUString aPrefix, aPostfix;
317 if( bUseOldNames )
319 aPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart."));
320 aPostfix = OUString( RTL_CONSTASCII_USTRINGPARAM("Diagram"));
322 else
324 aPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2."));
325 aPostfix = OUString( RTL_CONSTASCII_USTRINGPARAM("ChartType"));
328 if( rChartTypeService.match( aPrefix ))
330 sal_Int32 nSkip = aPrefix.getLength();
331 OSL_ASSERT( rChartTypeService.getLength() >= nSkip );
332 sal_Int32 nTypeLength = rChartTypeService.getLength() - nSkip - aPostfix.getLength();
333 // if postfix matches and leaves a non-empty type
334 if( nTypeLength > 0 && rChartTypeService.match( aPostfix, nSkip + nTypeLength ))
336 OUString aServiceName( rChartTypeService.copy( nSkip, nTypeLength ));
338 if( aServiceName.equalsAscii("Line"))
339 eResult = XML_LINE;
340 else if( aServiceName.equalsAscii("Area"))
341 eResult = XML_AREA;
342 else if( aServiceName.equalsAscii("Bar") ||
343 (!bUseOldNames && aServiceName.equalsAscii("Column")))
344 eResult = XML_BAR;
345 else if( aServiceName.equalsAscii("Pie"))
346 eResult = XML_CIRCLE;
347 else if( aServiceName.equalsAscii("Donut"))
348 eResult = XML_RING;
349 else if( (bUseOldNames && aServiceName.equalsAscii("XY")) ||
350 (!bUseOldNames && aServiceName.equalsAscii("Scatter")))
351 eResult = XML_SCATTER;
352 else if( aServiceName.equalsAscii("Bubble"))
353 eResult = XML_BUBBLE;
354 else if( aServiceName.equalsAscii("Net"))
355 eResult = XML_RADAR;
356 else if( aServiceName.equalsAscii("FilledNet"))
357 eResult = XML_FILLED_RADAR;
358 else if( (bUseOldNames && aServiceName.equalsAscii("Stock")) ||
359 (!bUseOldNames && aServiceName.equalsAscii("CandleStick")))
360 eResult = XML_STOCK;
364 if( eResult == XML_TOKEN_INVALID && rChartTypeService.getLength() > 0 )
365 eResult = XML_ADD_IN;
367 return eResult;
370 Reference< chart2::data::XLabeledDataSequence > GetNewLabeledDataSequence()
372 Reference< chart2::data::XLabeledDataSequence > xResult;
373 Reference< uno::XComponentContext > xContext( lcl_getComponentContext());
374 if( xContext.is() )
375 xResult.set(
376 xContext->getServiceManager()->createInstanceWithContext(
377 OUString::createFromAscii("com.sun.star.chart2.data.LabeledDataSequence"),
378 xContext ), uno::UNO_QUERY_THROW );
379 return xResult;
382 void CreateCategories(
383 const uno::Reference< chart2::data::XDataProvider > & xDataProvider,
384 const uno::Reference< chart2::XChartDocument > & xNewDoc,
385 const OUString & rRangeAddress,
386 sal_Int32 nCooSysIndex,
387 sal_Int32 nDimensionIndex,
388 tSchXMLLSequencesPerIndex * pLSequencesPerIndex )
392 if( xNewDoc.is() && rRangeAddress.getLength())
394 if( xDataProvider.is())
396 uno::Reference< chart2::XDiagram > xDia( xNewDoc->getFirstDiagram());
397 if( !xDia.is())
398 return;
400 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
401 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
402 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
403 if( nCooSysIndex < aCooSysSeq.getLength())
405 uno::Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
406 OSL_ASSERT( xCooSys.is());
407 if( nDimensionIndex < xCooSys->getDimension() )
409 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
410 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
412 uno::Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nI ));
413 if( xAxis.is() )
415 chart2::ScaleData aData( xAxis->getScaleData());
416 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
417 GetNewLabeledDataSequence());
420 OUString aConvertedRange( rRangeAddress );
421 bool bRangeConverted = false;
422 if( ! (xNewDoc->hasInternalDataProvider() &&
423 aConvertedRange.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("categories"))))
425 Reference< chart2::data::XRangeXMLConversion > xXMLConv( xDataProvider, uno::UNO_QUERY );
426 if( xXMLConv.is())
428 aConvertedRange = xXMLConv->convertRangeFromXML( rRangeAddress );
429 bRangeConverted = true;
432 Reference< chart2::data::XDataSequence > xSeq(
433 xDataProvider->createDataSequenceByRangeRepresentation( aConvertedRange ));
434 xLabeledSeq->setValues( xSeq );
435 if( bRangeConverted )
436 setXMLRangePropertyAtDataSequence( xSeq, rRangeAddress );
438 catch( const lang::IllegalArgumentException & ex )
440 (void)ex; // avoid warning for pro build
441 OSL_ENSURE( false, ::rtl::OUStringToOString(
442 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IllegalArgumentException caught, Message: " )) +
443 ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
445 aData.Categories.set( xLabeledSeq );
446 if( pLSequencesPerIndex )
448 // register for setting local data if external data provider is not present
449 pLSequencesPerIndex->insert(
450 tSchXMLLSequencesPerIndex::value_type(
451 tSchXMLIndexWithPart( SCH_XML_CATEGORIES_INDEX, SCH_XML_PART_VALUES ), xLabeledSeq ));
453 xAxis->setScaleData( aData );
461 catch( uno::Exception & )
463 OSL_ENSURE( false, "Exception caught while creating Categories" );
468 uno::Any getPropertyFromContext( const rtl::OUString& rPropertyName, const XMLPropStyleContext* pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
470 uno::Any aRet;
471 if( !pPropStyleContext || !pStylesCtxt )
472 return aRet;
473 const ::std::vector< XMLPropertyState >& rProperties = pPropStyleContext->GetProperties();
474 const UniReference< XMLPropertySetMapper >& rMapper = pStylesCtxt->GetImportPropertyMapper( pPropStyleContext->GetFamily()/*XML_STYLE_FAMILY_SCH_CHART_ID*/ )->getPropertySetMapper();
475 ::std::vector< XMLPropertyState >::const_iterator aEnd( rProperties.end() );
476 ::std::vector< XMLPropertyState >::const_iterator aPropIter( rProperties.begin() );
477 for( aPropIter = rProperties.begin(); aPropIter != aEnd; ++aPropIter )
479 sal_Int32 nIdx = aPropIter->mnIndex;
480 if( nIdx == -1 )
481 continue;
482 OUString aPropName = rMapper->GetEntryAPIName( nIdx );
483 if(rPropertyName.equals(aPropName))
484 return aPropIter->maValue;
486 return aRet;
489 void exportText( SvXMLExport& rExport, const OUString& rText, bool bConvertTabsLFs )
491 SvXMLElementExport aPara( rExport, XML_NAMESPACE_TEXT,
492 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_P ),
493 sal_True, sal_False );
495 if( bConvertTabsLFs )
497 sal_Int32 nStartPos = 0;
498 sal_Int32 nEndPos = rText.getLength();
499 sal_Unicode cChar;
501 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
503 cChar = rText[ nPos ];
504 switch( cChar )
506 case 0x0009: // tabulator
508 if( nPos > nStartPos )
509 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) );
510 nStartPos = nPos + 1;
512 SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT,
513 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_TAB_STOP ),
514 sal_False, sal_False );
516 break;
518 case 0x000A: // linefeed
520 if( nPos > nStartPos )
521 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) );
522 nStartPos = nPos + 1;
524 SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT,
525 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_LINE_BREAK ),
526 sal_False, sal_False );
528 break;
531 if( nEndPos > nStartPos )
533 if( nStartPos == 0 )
534 rExport.GetDocHandler()->characters( rText );
535 else
536 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nEndPos - nStartPos)) );
539 else // do not convert tabs and linefeeds (eg for numbers coming from unit converter)
541 rExport.GetDocHandler()->characters( rText );
545 Reference< chart2::XRegressionCurve > getRegressionCurve(
546 const Reference< chart2::XDataSeries > & xDataSeries )
548 Reference< chart2::XRegressionCurve > xResult;
550 Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xDataSeries, uno::UNO_QUERY );
551 if( xRegCurveCnt.is())
553 // find equation properties of first regression curve
554 Sequence< Reference< chart2::XRegressionCurve > > aCurveSeq(
555 xRegCurveCnt->getRegressionCurves() );
556 for( sal_Int32 nI=0; nI<aCurveSeq.getLength(); ++nI )
558 // skip mean-value line
559 Reference< lang::XServiceName > xServiceName( aCurveSeq[nI], uno::UNO_QUERY );
560 if( xServiceName.is())
562 OUString aServiceName( xServiceName->getServiceName());
563 if( aServiceName.equalsAsciiL(
564 RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.MeanValueRegressionCurve" )))
565 continue;
567 // take first non-empty curve
568 if( aCurveSeq[nI].is())
570 xResult.set( aCurveSeq[nI] );
571 break;
575 return xResult;
578 void setXMLRangePropertyAtDataSequence(
579 const Reference< chart2::data::XDataSequence > & xDataSequence,
580 const OUString & rXMLRange )
582 if( !xDataSequence.is())
583 return;
586 const OUString aXMLRangePropName( RTL_CONSTASCII_USTRINGPARAM( "CachedXMLRange" ));
587 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
588 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
589 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
590 xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
592 catch( const uno::Exception & ex )
594 (void)ex; // avoid warning for pro build
595 OSL_ENSURE( false, ::rtl::OUStringToOString(
596 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught, Message: " )) +
597 ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
601 bool getXMLRangePropertyFromDataSequence(
602 const Reference< chart2::data::XDataSequence > & xDataSequence,
603 OUString & rOutXMLRange,
604 bool bClearProp /* = false */)
606 bool bResult = false;
607 if( xDataSequence.is())
611 const OUString aXMLRangePropName( RTL_CONSTASCII_USTRINGPARAM( "CachedXMLRange" ));
612 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
613 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
614 bResult =
615 ( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ) &&
616 ( xProp->getPropertyValue( aXMLRangePropName ) >>= rOutXMLRange ) &&
617 rOutXMLRange.getLength());
618 // clear the property after usage
619 if( bClearProp && bResult )
620 xProp->setPropertyValue( aXMLRangePropName, uno::Any( OUString()));
622 catch( const uno::Exception & ex )
624 (void)ex; // avoid warning for pro build
625 OSL_ENSURE( false, ::rtl::OUStringToOString(
626 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught, Message: " )) +
627 ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
630 return bResult;
633 void copyProperties(
634 const Reference< beans::XPropertySet > & xSource,
635 const Reference< beans::XPropertySet > & xDestination )
637 if( ! (xSource.is() && xDestination.is()) )
638 return;
642 Reference< beans::XPropertySetInfo > xSrcInfo( xSource->getPropertySetInfo(), uno::UNO_QUERY_THROW );
643 Reference< beans::XPropertySetInfo > xDestInfo( xDestination->getPropertySetInfo(), uno::UNO_QUERY_THROW );
644 Sequence< beans::Property > aProperties( xSrcInfo->getProperties());
645 const sal_Int32 nLength = aProperties.getLength();
646 for( sal_Int32 i = 0; i < nLength; ++i )
648 OUString aName( aProperties[i].Name);
649 if( xDestInfo->hasPropertyByName( aName ))
651 beans::Property aProp( xDestInfo->getPropertyByName( aName ));
652 if( (aProp.Attributes & beans::PropertyAttribute::READONLY) == 0 )
653 xDestination->setPropertyValue(
654 aName, xSource->getPropertyValue( aName ));
658 catch( const uno::Exception & )
660 OSL_ENSURE( false, "Copying property sets failed!" );
664 bool switchBackToDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc, const tSchXMLLSequencesPerIndex & rLSequencesPerIndex )
666 //return whether the switch is successful
667 if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
668 return false;
669 Reference< chart2::data::XDataProvider > xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc ) );
670 if( !xDataProviderFromParent.is() )
671 return false;
672 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartDoc, uno::UNO_QUERY );
673 if( !xDataReceiver.is() )
674 return false;
676 xDataReceiver->attachDataProvider( xDataProviderFromParent );
678 for( tSchXMLLSequencesPerIndex::const_iterator aLSeqIt( rLSequencesPerIndex.begin() );
679 aLSeqIt != rLSequencesPerIndex.end(); ++aLSeqIt )
681 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( aLSeqIt->second );
682 if( !xLabeledSeq.is() )
683 continue;
684 Reference< chart2::data::XDataSequence > xNewSeq;
685 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getValues(), xDataProviderFromParent );
686 if( xNewSeq.is() )
687 xLabeledSeq->setValues( xNewSeq );
688 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getLabel(), xDataProviderFromParent );
689 if( xNewSeq.is() )
690 xLabeledSeq->setLabel( xNewSeq );
692 return true;
695 void setBuildIDAtImportInfo( uno::Reference< frame::XModel > xModel, Reference< beans::XPropertySet > xImportInfo )
697 ::rtl::OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xModel) );
698 if( aGenerator.getLength() )
699 SvXMLMetaDocumentContext::setBuildId( aGenerator, xImportInfo );
702 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference< frame::XModel >& xChartModel )
704 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel );
705 if( !bResult )
707 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
708 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/680m") ) ) != -1 )
709 bResult= true;
711 return bResult;
714 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference< frame::XModel >& xChartModel )
716 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ) )
717 return true;
719 if( isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel ) )
721 sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) );
722 if( nBuilId>0 && nBuilId<=9238 ) //9238 is build id of OpenOffice.org 2.3.1
723 return true;
725 return false;
728 bool isDocumentGeneratedWithOpenOfficeOlderThan2_3( const uno::Reference< frame::XModel >& xChartModel )
730 bool bResult = false;
731 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
732 //if there is a meta stream at the chart object it was not written with an older OpenOffice version < 2.3
733 if( !aGenerator.getLength() )
735 //if there is no meta stream at the chart object we need to check whether the parent document is OpenOffice at all
736 uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
737 if( xChild.is() )
739 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
740 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project") ) ) != -1 )
742 //the chart application has not created files without a meta stream since OOo 2.3 (OOo 2.3 has written a metastream already)
743 //only the report builder extension has created some files with OOo 3.1 that do not have a meta stream
744 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/31") ) ) != -1 )
745 bResult = false;//#i100102# probably generated with OOo 3.1 by the report designer
746 else
747 bResult= true; //in this case the OLE chart was created by an older version, as OLE objects are sometimes stream copied the version can differ from the parents version, so the parents version is not a reliable indicator
749 else if( isDocumentGeneratedWithOpenOfficeOlderThan2_0(xChartModel) )
750 bResult= true;
753 return bResult;
756 bool isDocumentGeneratedWithOpenOfficeOlderThan2_0( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel)
758 bool bResult = false;
759 ::rtl::OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xChartModel) );
760 if( ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org 1") ) ) == 0 )
761 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarOffice 6") ) ) == 0 )
762 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarOffice 7") ) ) == 0 )
763 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarSuite 6") ) ) == 0 )
764 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarSuite 7") ) ) == 0 )
766 bResult= true;
767 return bResult;
770 Reference< chart2::data::XDataProvider > getDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc )
772 Reference< chart2::data::XDataProvider > xRet;
773 uno::Reference< container::XChild > xChild( xChartDoc, uno::UNO_QUERY );
774 if( xChild.is() )
776 Reference< lang::XMultiServiceFactory > xFact( xChild->getParent(), uno::UNO_QUERY );
777 if( xFact.is() )
779 const OUString aDataProviderServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.data.DataProvider"));
780 const uno::Sequence< OUString > aServiceNames( xFact->getAvailableServiceNames());
781 const OUString * pBegin = aServiceNames.getConstArray();
782 const OUString * pEnd = pBegin + aServiceNames.getLength();
783 if( ::std::find( pBegin, pEnd, aDataProviderServiceName ) != pEnd )
785 xRet = Reference< chart2::data::XDataProvider >(
786 xFact->createInstance( aDataProviderServiceName ), uno::UNO_QUERY );
790 return xRet;
793 } // namespace SchXMLTools