/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#include <xmloff/xmlprmap.hxx>

#include "SchXMLExport.hxx"
#include "XMLChartPropertySetMapper.hxx"
#include "SchXMLSeriesHelper.hxx"
#include "ColorPropertySet.hxx"
#include "SchXMLTools.hxx"
#include "SchXMLEnumConverter.hxx"

#include <tools/debug.hxx>
#include <rtl/logfile.hxx>
#include <comphelper/processfactory.hxx>
#include <tools/globname.hxx>
#include <sot/clsids.hxx>

#include <xmloff/nmspmap.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/families.hxx>
#include <xmloff/xmlaustp.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmlmetae.hxx>
#include "xexptran.hxx"
#include <rtl/math.hxx>
// header for any2enum
#include <comphelper/extract.hxx>

#include <list>
#include <typeinfo>
#include <algorithm>

#include <com/sun/star/task/XStatusIndicatorSupplier.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/util/XRefreshable.hpp>

#include <com/sun/star/chart/XAxis.hpp>
#include <com/sun/star/chart/XAxisSupplier.hpp>
#include <com/sun/star/chart/XChartDocument.hpp>
#include <com/sun/star/chart/ChartLegendPosition.hpp>
#include <com/sun/star/chart/ChartLegendExpansion.hpp>
#include <com/sun/star/chart/ChartDataRowSource.hpp>
#include <com/sun/star/chart/ChartAxisAssign.hpp>
#include <com/sun/star/chart/ChartAxisType.hpp>
#include <com/sun/star/chart/TimeIncrement.hpp>
#include <com/sun/star/chart/TimeInterval.hpp>
#include <com/sun/star/chart/TimeUnit.hpp>
#include <com/sun/star/chart/ChartSeriesAddress.hpp>
#include <com/sun/star/chart/X3DDisplay.hpp>
#include <com/sun/star/chart/XStatisticDisplay.hpp>
#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
#include <com/sun/star/chart/XDiagramPositioning.hpp>

#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/XDiagram.hpp>
#include <com/sun/star/chart2/RelativePosition.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
#include <com/sun/star/chart2/data/XDataSource.hpp>
#include <com/sun/star/chart2/data/XDataSink.hpp>
#include <com/sun/star/chart2/data/XDataReceiver.hpp>
#include <com/sun/star/chart2/data/XDataProvider.hpp>
#include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
#include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>

#include <com/sun/star/util/XStringMapping.hpp>
#include <com/sun/star/drawing/HomogenMatrix.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/drawing/XShapes.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/embed/XVisualObject.hpp>
#include <com/sun/star/container/XChild.hpp>


#include "MultiPropertySetHandler.hxx"
#include "PropertyMap.hxx"

using namespace com::sun::star;
using namespace ::xmloff::token;

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::rtl::OUStringToOString;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
using ::std::vector;

// ========================================
// class SchXMLExportHelper_Impl
// ========================================

class SchXMLExportHelper_Impl
{
public:
    // first: data sequence for label, second: data sequence for values.
    typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >,
            ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > tLabelValuesDataPair;
    typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont;

public:
	SchXMLExportHelper_Impl( SvXMLExport& rExport,
						SvXMLAutoStylePoolP& rASPool );

    virtual ~SchXMLExportHelper_Impl();

    // auto-styles
	/// parse chart and collect all auto-styles used in current pool
	void collectAutoStyles( com::sun::star::uno::Reference<
							com::sun::star::chart::XChartDocument > rChartDoc );

    /// write the styles collected into the current pool as <style:style> elements
	void exportAutoStyles();

    /** export the <chart:chart> element corresponding to rChartDoc
		if bIncludeTable is true, the chart data is exported as <table:table>
		element (inside the chart element).

		Otherwise the external references stored in the chart document are used
		for writing the corresponding attributes at series

		All attributes contained in xAttrList are written at the chart element,
		which ist the outer element of a chart. So these attributes can easily
		be parsed again by the container
	 */
	void exportChart( com::sun::star::uno::Reference<
					  	com::sun::star::chart::XChartDocument > rChartDoc,
					  sal_Bool bIncludeTable );

    UniReference< XMLPropertySetMapper > GetPropertySetMapper() const;

    void SetChartRangeAddress( const ::rtl::OUString& rAddress )
        { msChartAddress = rAddress; }
    void SetTableNumberList( const ::rtl::OUString& rList )
        { msTableNumberList = rList; }

    void InitRangeSegmentationProperties(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartDocument > & xChartDoc );

    ::com::sun::star::awt::Size getPageSize(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartDocument > & xChartDoc ) const;

    /** first parseDocument: collect autostyles and store names in this queue
        second parseDocument: export content and use names from this queue
     */
    ::std::queue< ::rtl::OUString > maAutoStyleNameQueue;
    void CollectAutoStyle(
        const std::vector< XMLPropertyState >& aStates );
    void AddAutoStyleAttribute(
        const std::vector< XMLPropertyState >& aStates );

    SvXMLAutoStylePoolP& GetAutoStylePoolP()
    { return mrAutoStylePool; }

	/// if bExportContent is false the auto-styles are collected
	void parseDocument( com::sun::star::uno::Reference<
							com::sun::star::chart::XChartDocument >& rChartDoc,
						sal_Bool bExportContent,
						sal_Bool bIncludeTable = sal_False );
	void exportTable();
	void exportPlotArea(
        com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > xDiagram,
        com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > xNewDiagram,
        const ::com::sun::star::awt::Size & rPageSize,
        sal_Bool bExportContent,
        sal_Bool bIncludeTable );
    void exportCoordinateRegion( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram >& xDiagram );
	void exportAxes( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > & xDiagram,
                                    const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
                                    sal_Bool bExportContent );
    void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
                    const Reference< beans::XPropertySet > xAxisProps, const Reference< chart2::XAxis >& xChart2Axis,
                    const OUString& rCategoriesRanges,
                    bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
    void exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent );
    void exportDateScale( const Reference< beans::XPropertySet > xAxisProps );
    void exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent );

	void exportSeries(
        const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
        const ::com::sun::star::awt::Size & rPageSize,
        sal_Bool bExportContent,
        sal_Bool bHasTwoYAxes );
    void exportCandleStickSeries(
        const ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDataSeries > > & aSeriesSeq,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        sal_Bool bJapaneseCandleSticks,
        sal_Bool bExportContent );
    void exportDataPoints(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::beans::XPropertySet > & xSeriesProperties,
        sal_Int32 nSeriesLength,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        sal_Bool bExportContent );
    void exportRegressionCurve(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries > & xSeries,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::beans::XPropertySet > & xSeriesProp,
        const ::com::sun::star::awt::Size & rPageSize,
        sal_Bool bExportContent );

	/// add svg position as attribute for current element
    void addPosition( const ::com::sun::star::awt::Point & rPosition );
	void addPosition( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape );
	/// add svg size as attribute for current element
    void addSize( const ::com::sun::star::awt::Size & rSize, bool bIsOOoNamespace = false );
    void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape, bool bIsOOoNamespace = false  );
	/// fills the member msString with the appropriate String (i.e. "A3")
	void getCellAddress( sal_Int32 nCol, sal_Int32 nRow );
    /// exports a string as a paragraph element
    void exportText( const ::rtl::OUString& rText, bool bConvertTabsLFs = false );
    void exportErrorBarRanges();

    SchXMLExportHelper_Impl(SchXMLExportHelper_Impl &); // not defined
    void operator =(SchXMLExportHelper_Impl &); // not defined

public:
	SvXMLExport& mrExport;
	SvXMLAutoStylePoolP& mrAutoStylePool;
	UniReference< XMLPropertyHandlerFactory > mxPropertyHandlerFactory;
	UniReference< XMLPropertySetMapper > mxPropertySetMapper;
	UniReference< XMLChartExportPropertyMapper > mxExpPropMapper;

	rtl::OUString msTableName;
	rtl::OUStringBuffer msStringBuffer;
	rtl::OUString msString;

    // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
	sal_Bool mbHasSeriesLabels;
	sal_Bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
	sal_Bool mbRowSourceColumns;
	rtl::OUString msChartAddress;
	rtl::OUString msTableNumberList;
    ::com::sun::star::uno::Sequence< sal_Int32 > maSequenceMapping;

	rtl::OUString msCLSID;

    ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes;

    tDataSequenceCont m_aDataSequencesToExport;
    rtl::OUString maCategoriesRange;
};

namespace
{
Reference< uno::XComponentContext > lcl_getComponentContext()
{
    Reference< uno::XComponentContext > xContext;
    try
    {
        Reference< beans::XPropertySet > xFactProp( comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
        if( xFactProp.is())
            xFactProp->getPropertyValue(OUString::createFromAscii("DefaultContext")) >>= xContext;
    }
    catch( uno::Exception& )
    {}

    return xContext;
}

class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
{
public:
    explicit lcl_MatchesRole( const OUString & aRole ) :
            m_aRole( aRole )
    {}

    bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
    {
        if( !xSeq.is() )
            return  false;
        Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
        OUString aRole;

        return ( xProp.is() &&
                 (xProp->getPropertyValue(
                     OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) &&
                 m_aRole.equals( aRole ));
    }

private:
    OUString m_aRole;
};

template< typename T >
    void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
{
    rDestination.reserve( rDestination.size() + rSource.getLength());
    ::std::copy( rSource.getConstArray(), rSource.getConstArray() + rSource.getLength(),
                 ::std::back_inserter( rDestination ));
}

template< typename T >
    void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
{
    rDestination.clear();
    lcl_SequenceToVectorAppend( rSource, rDestination );
}

Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
{
    Reference< chart2::data::XLabeledDataSequence >  xResult;
    try
    {
        Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
            xDiagram, uno::UNO_QUERY_THROW );
        Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
            xCooSysCnt->getCoordinateSystems());
        for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
        {
            Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
            OSL_ASSERT( xCooSys.is());
            for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
            {
                const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
                for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
                {
                    Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
                    OSL_ASSERT( xAxis.is());
                    if( xAxis.is())
                    {
                        chart2::ScaleData aScaleData = xAxis->getScaleData();
                        if( aScaleData.Categories.is())
                        {
                            xResult.set( aScaleData.Categories );
                            break;
                        }
                    }
                }
            }
        }
    }
    catch( uno::Exception & ex )
    {
        (void)ex; // avoid warning for pro build
        OSL_ENSURE( false, OUStringToOString(
                        OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
                        OUString::createFromAscii( typeid( ex ).name()) +
                        OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
                        ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
    }

    return xResult;
}

Reference< chart2::data::XDataSource > lcl_createDataSource(
    const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
{
    Reference< chart2::data::XDataSink > xSink;
    Reference< uno::XComponentContext > xContext( lcl_getComponentContext());
    if( xContext.is() )
        xSink.set(
            xContext->getServiceManager()->createInstanceWithContext(
                OUString::createFromAscii("com.sun.star.chart2.data.DataSource"),
                xContext ), uno::UNO_QUERY_THROW );
    if( xSink.is())
        xSink->setData( aData );

    return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
}

Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
{
    ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
    if( xChartDoc.is() )
    {
        Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
        ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
        for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
            ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
        {
            Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
            if( !xDataSource.is() )
                continue;
            uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
            lcl_SequenceToVectorAppend( aDataSequences, aContainer );
        }
    }

    Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
    ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());

    return aRet;
}

Reference< chart2::data::XLabeledDataSequence >
    lcl_getDataSequenceByRole(
        const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
        const OUString & rRole )
{
    Reference< chart2::data::XLabeledDataSequence > aNoResult;

    const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
    const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
    const Reference< chart2::data::XLabeledDataSequence > * pMatch =
        ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));

    if( pMatch != pEnd )
        return *pMatch;

    return aNoResult;
}

Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, sal_Bool& rOutSourceHasCategoryLabels )
{
    ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;

    //categories are always the first sequence
    Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
    Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
    if( xCategories.is() )
        aLabeledSeqVector.push_back( xCategories );
    rOutSourceHasCategoryLabels = sal_Bool(xCategories.is());

    Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
            lcl_getAllSeriesSequences( xChartDoc ) );

    //the first x-values is always the next sequence //todo ... other x-values get lost for old format
    Reference< chart2::data::XLabeledDataSequence > xXValues(
        lcl_getDataSequenceByRole( aSeriesSeqVector, OUString::createFromAscii("values-x" ) ) );
    if( xXValues.is() )
        aLabeledSeqVector.push_back( xXValues );

    //add all other sequences now without x-values
    lcl_MatchesRole aHasXValues( OUString::createFromAscii("values-x" ) );
    for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
    {
        if( !aHasXValues( aSeriesSeqVector[nN] ) )
            aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
    }

    Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
    ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );

    return lcl_createDataSource( aSeq );
}

bool lcl_isSeriesAttachedToFirstAxis(
    const Reference< chart2::XDataSeries > & xDataSeries )
{
    bool bResult=true;

    try
    {
        sal_Int32 nAxisIndex = 0;
        Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
        if( xProp.is() )
            xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("AttachedAxisIndex") ) ) >>= nAxisIndex;
        bResult = (0==nAxisIndex);
    }
    catch( uno::Exception & ex )
    {
        (void)ex; // avoid warning for pro build
        OSL_ENSURE( false, OUStringToOString(
                        OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
                        OUString::createFromAscii( typeid( ex ).name()) +
                        OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
                        ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
    }

    return bResult;
}

OUString lcl_ConvertRange( const ::rtl::OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
{
    OUString aResult = rRange;
    if( !xDoc.is() )
        return aResult;
    Reference< chart2::data::XRangeXMLConversion > xConversion(
        xDoc->getDataProvider(), uno::UNO_QUERY );
    if( xConversion.is())
        aResult = xConversion->convertRangeToXML( rRange );
    return aResult;
}

typedef ::std::pair< OUString, OUString > tLabelAndValueRange;

tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
    const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
    const OUString & rRole,
    const Reference< chart2::XChartDocument > & xDoc,
    SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
{
    tLabelAndValueRange aResult;

    Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
        lcl_getDataSequenceByRole( aSeqCnt, rRole ));
    if( xLabeledSeq.is())
    {
        Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
        if( xLabelSeq.is())
            aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );

        Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
        if( xValueSeq.is())
            aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );

        if( xLabelSeq.is() || xValueSeq.is())
            rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq ));
    }

    return aResult;
}

sal_Int32 lcl_getSequenceLengthByRole(
    const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
    const OUString & rRole )
{
    Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
        lcl_getDataSequenceByRole( aSeqCnt, rRole ));
    if( xLabeledSeq.is())
    {
        Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
        return xSeq->getData().getLength();
    }
    return 0;
}

bool lcl_hasChartType( const Reference< chart2::XDiagram > & xDiagram, const OUString & rChartType )
{
    try
    {
        Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
        Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
        for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
        {
            Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
            Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
            for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
            {
                if( aChartTypes[nCTIdx]->getChartType().equals( rChartType ))
                    return true;
            }
        }
    }
    catch( uno::Exception & )
    {
        DBG_ERROR( "Exception while searching for chart type in diagram" );
    }
    return false;
}

OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
{
    OUStringBuffer aResult;
    bool bPrecedeWithSpace = false;
    for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
    {
        if( rSequence[nIndex].getLength())
        {
            if( bPrecedeWithSpace )
                aResult.append( static_cast< sal_Unicode >( ' ' ));
            aResult.append( rSequence[nIndex] );
            bPrecedeWithSpace = true;
        }
    }
    return aResult.makeStringAndClear();
}

void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
{
    uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
    if( xTextualDataSequence.is())
    {
        rOutLabels = xTextualDataSequence->getTextualData();
    }
    else if( xLabelSeq.is())
    {
        Sequence< uno::Any > aAnies( xLabelSeq->getData());
        rOutLabels.realloc( aAnies.getLength());
        for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
            aAnies[i] >>= rOutLabels[i];
    }
}

sal_Int32 lcl_getMaxSequenceLength(
    const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
{
    sal_Int32 nResult = 0;
    for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin());
         aIt != rContainer.end(); ++aIt )
    {
        if( aIt->second.is())
        {
            sal_Int32 nSeqLength = aIt->second->getData().getLength();
            if( nSeqLength > nResult )
                nResult = nSeqLength;
        }
    }
    return nResult;
}

uno::Sequence< rtl::OUString > lcl_DataSequenceToStringSequence(
    const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
{
    uno::Sequence< rtl::OUString > aResult;
    if(!xDataSequence.is())
        return aResult;

    uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
    if( xTextualDataSequence.is() )
    {
        aResult = xTextualDataSequence->getTextualData();
    }
    else
    {
        uno::Sequence< uno::Any > aValues = xDataSequence->getData();
        aResult.realloc(aValues.getLength());

        for(sal_Int32 nN=aValues.getLength();nN--;)
            aValues[nN] >>= aResult[nN];
    }

    return aResult;
}
::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
{
    double fNan = 0.0;
    ::rtl::math::setNan( &fNan );
    ::std::vector< double > aResult;
    if(!xSeq.is())
        return aResult;

    uno::Sequence< double > aValuesSequence;
    Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
    if( xNumSeq.is() )
    {
        aValuesSequence = xNumSeq->getNumericalData();
    }
    else
    {
        Sequence< uno::Any > aAnies( xSeq->getData() );
        aValuesSequence.realloc( aAnies.getLength() );
        for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
            aAnies[i] >>= aValuesSequence[i];
    }

    //special handling for x-values (if x-values do point to categories, indices are used instead )
    Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
    if( xProp.is() )
    {
        OUString aRole;
        xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Role") ) ) >>= aRole;
        if( aRole.match( OUString( RTL_CONSTASCII_USTRINGPARAM( "values-x") ) ) )
        {
            //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
            bool bHasValue=false;
            bool bHasText=false;
            sal_Int32 nCount = aValuesSequence.getLength();
            for( sal_Int32 j = 0; j < nCount; ++j )
            {
                if( !::rtl::math::isNan( aValuesSequence[j] ) )
                {
                    bHasValue=true;
                    break;
                }
            }
            if(!bHasValue)
            {
                //no double value is countained
                //is there any text?
                uno::Sequence< rtl::OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
                sal_Int32 nTextCount = aStrings.getLength();
                for( sal_Int32 j = 0; j < nTextCount; ++j )
                {
                    if( aStrings[j].getLength() )
                    {
                        bHasText=true;
                        break;
                    }
                }
            }
            if( !bHasValue && bHasText )
            {
                for( sal_Int32 j = 0; j < nCount; ++j )
                    aValuesSequence[j] = j+1;
            }
        }
    }

    ::std::copy( aValuesSequence.getConstArray(), aValuesSequence.getConstArray() + aValuesSequence.getLength(),
                     ::std::back_inserter( aResult ));
    return aResult;
}

bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
{
    if( !xDataSequence.is() )
        return false;
    uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
    if( xProp.is() )
    {
        uno::Sequence< sal_Int32 > aHiddenValues;
        try
        {
            xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HiddenValues" ) ) ) >>= aHiddenValues;
            if( !aHiddenValues.getLength() )
                return true;
        }
        catch( uno::Exception& e )
        {
            (void)e; // avoid warning
            return true;
        }
    }
    if( xDataSequence->getData().getLength() )
        return true;
    return false;
}

typedef vector< OUString > tStringVector;
typedef vector< double > tDoubleVector;
typedef vector< vector< OUString > > t2DStringVector;
typedef vector< vector< double > > t2DNumberContainer;

struct lcl_TableData
{
    t2DNumberContainer  aDataInRows;
    tStringVector       aDataRangeRepresentations;

    tStringVector       aColumnDescriptions;
    tStringVector       aColumnDescriptions_Ranges;

    tStringVector       aRowDescriptions;
    tStringVector       aRowDescriptions_Ranges;

    Sequence< Sequence< uno::Any > >    aComplexColumnDescriptions;//outer index is columns - inner index is level
    Sequence< Sequence< uno::Any > >    aComplexRowDescriptions;//outer index is rows - inner index is level

    ::std::vector< sal_Int32 > aHiddenColumns;
};

// ::std::bind2nd( ::std::mem_fun_ref( &T::resize ), nSize ) does not work
template< class T >
    struct lcl_resize
    {
        lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {}
        void operator()( T & t )
        { t.resize( m_nSize, m_fDefaultValue ); }
    private:
        typename T::size_type m_nSize;
        typename T::value_type m_fDefaultValue;
    };


typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
    lcl_DataSequenceMap;

struct lcl_SequenceToMapElement :
    public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type >
{
    lcl_SequenceToMapElement()
    {}
    result_type operator() ( const argument_type & rContent )
    {
        sal_Int32 nIndex = -1;
        if( rContent.second.is()) //has values
        {
            OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
            nIndex = aRangeRep.toInt32();
        }
        else if( rContent.first.is()) //has labels
            nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
        return result_type( nIndex, rContent );
    }
};

void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
    SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences )
{
    lcl_DataSequenceMap aIndexSequenceMap;
    ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
                      ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
                      lcl_SequenceToMapElement());

    rInOutSequences.clear();
    sal_Int32 nIndex = 0;
    for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin();
         aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex )
    {
        if( aIt->first < 0 )
            continue;
        // fill empty columns
        for( ; nIndex < aIt->first; ++nIndex )
            rInOutSequences.push_back(
                SchXMLExportHelper_Impl::tDataSequenceCont::value_type( 0, 0 ));
        OSL_ASSERT( nIndex == aIt->first );
        rInOutSequences.push_back( aIt->second );
    }
}


lcl_TableData lcl_getDataForLocalTable(
    const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
    const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
    const OUString& rCategoriesRange,
    bool bSeriesFromColumns,
    const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
{
    lcl_TableData aResult;

    try
    {
        Sequence< OUString > aSimpleCategories;
        if( xAnyDescriptionAccess.is() )
        {
            //categories
            if( bSeriesFromColumns )
            {
                aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
                aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
            }
            else
            {
                aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
                aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
            }
        }

        //series values and series labels
        SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
        SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin());
        SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end());
        SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin );

        size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
        size_t nCategoriesLength( aSimpleCategories.getLength() );
        if( nCategoriesLength > nMaxSequenceLength )
        {
            aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
            nCategoriesLength = nMaxSequenceLength;
        }
        size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
        size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );

        // resize data
        aResult.aDataInRows.resize( nNumRows );
        double fNan = 0.0;
        ::rtl::math::setNan( &fNan );
        ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(),
                         lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan ));
        aResult.aColumnDescriptions.resize( nNumColumns );
        aResult.aComplexColumnDescriptions.realloc( nNumColumns );
        aResult.aRowDescriptions.resize( nNumRows );
        aResult.aComplexRowDescriptions.realloc( nNumRows );

        tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions    : aResult.aColumnDescriptions;
        tStringVector& rLabels     = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;

        //categories
        lcl_SequenceToVector( aSimpleCategories, rCategories );
        if( rCategoriesRange.getLength() )
        {
            OUString aRange(rCategoriesRange);
            if( xRangeConversion.is())
                aRange = xRangeConversion->convertRangeToXML( aRange );
            if( bSeriesFromColumns )
                aResult.aRowDescriptions_Ranges.push_back( aRange );
            else
                aResult.aColumnDescriptions_Ranges.push_back( aRange );
        }

        // iterate over all sequences
        size_t nSeqIdx = 0;
        Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
        for( ; aIt != aEnd; ++aIt, ++nSeqIdx )
        {
            OUString aRange;
            Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
            if( aIt->first.is())
            {
                lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first );
                rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
                aRange = aIt->first->getSourceRangeRepresentation();
                if( xRangeConversion.is())
                    aRange = xRangeConversion->convertRangeToXML( aRange );
            }
            else if( aIt->second.is())
            {
                rCurrentComplexLabel.realloc(1);
                rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
                    aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
            }
            if( bSeriesFromColumns )
                aResult.aColumnDescriptions_Ranges.push_back( aRange );
            else
                aResult.aRowDescriptions_Ranges.push_back( aRange );

            ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second ));
            if( bSeriesFromColumns )
            {
                const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
                for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
                    aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
            }
            else
                aResult.aDataInRows[nSeqIdx] = aNumbers;

            if( aIt->second.is())
            {
                aRange =  aIt->second->getSourceRangeRepresentation();
                if( xRangeConversion.is())
                    aRange = xRangeConversion->convertRangeToXML( aRange );
            }
            aResult.aDataRangeRepresentations.push_back( aRange );

            //is column hidden?
            if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) )
                aResult.aHiddenColumns.push_back(nSeqIdx);
        }
        Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
        rComplexAnyLabels.realloc(aComplexLabels.getLength());
        for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
        {
            Sequence< OUString >& rSource = aComplexLabels[nN];
            Sequence< Any >& rTarget = rComplexAnyLabels[nN];
            rTarget.realloc( rSource.getLength() );
            for( sal_Int32 i=0; i<rSource.getLength(); i++ )
                rTarget[i] = uno::makeAny( rSource[i] );
        }
    }
    catch( uno::Exception & rEx )
    {
        (void)rEx; // avoid warning for pro build
        OSL_TRACE( OUStringToOString( OUString( RTL_CONSTASCII_USTRINGPARAM(
                    "something went wrong during table data collection: " )) + rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
    }

    return aResult;
}

void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
                                        SvXMLExport& rExport )
{
    if( xPropSet.is())
    {
        sal_Int32 nNumberFormat = 0;
        Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
        if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
            rExport.addDataStyle( nNumberFormat );
    }
}

::std::vector< Reference< chart2::data::XDataSequence > >
    lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
{
    ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
    Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
    if( !xErrorBarDataSource.is())
        return aResult;

    const OUString aRolePrefix( RTL_CONSTASCII_USTRINGPARAM( "error-bars-" ));
//     const OUString aXRolePrefix( aRolePrefix + OUString( RTL_CONSTASCII_USTRINGPARAM( "x-" )));
//     const OUString aYRolePrefix( aRolePrefix + OUString( RTL_CONSTASCII_USTRINGPARAM( "y-" )));
//     const OUString aPositivePostfix( RTL_CONSTASCII_USTRINGPARAM( "positive" ));
//     const OUString aNegativePostfix( RTL_CONSTASCII_USTRINGPARAM( "negative" ));

    Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
        xErrorBarDataSource->getDataSequences());
    for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
    {
        try
        {
            if( aSequences[nI].is())
            {
                Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
                Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
                OUString aRole;
                if( ( xSeqProp->getPropertyValue(
                          OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" ))) >>= aRole ) &&
                    aRole.match( aRolePrefix ))
                {
                    aResult.push_back( xSequence );
                }
            }
        }
        catch( uno::Exception & rEx )
        {
#ifdef DBG_UTIL
            String aStr( rEx.Message );
            ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
            DBG_ERROR1( "chart:exporting error bar ranges: %s", aBStr.GetBuffer());
#else
            (void)rEx; // avoid warning
#endif
        }
    }

    return aResult;
}

bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence > xValues, rtl::OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
{
    bool bDomainExported = false;
    if( xValues.is())
    {
        Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
        OUString aRange( lcl_ConvertRange( xValues->getSourceRangeRepresentation(), xNewDoc ) );

        //work around error in OOo 2.0 (problems with multiple series having a domain element)
        if( !rFirstRangeForThisDomainIndex.getLength() || !aRange.equals(rFirstRangeForThisDomainIndex) )
        {
            rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange);
            SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, sal_True, sal_True );
            bDomainExported = true;
        }

        if( !rFirstRangeForThisDomainIndex.getLength() )
            rFirstRangeForThisDomainIndex = aRange;
    }
    return bDomainExported;
}

} // anonymous namespace

struct SchXMLDataPointStruct
{
    OUString   maStyleName;
    sal_Int32  mnRepeat;

    SchXMLDataPointStruct() : mnRepeat( 1 ) {}
};

// ========================================
// class SchXMLExportHelper
// ========================================

SchXMLExportHelper::SchXMLExportHelper(	SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
    : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
{
}

SchXMLExportHelper::~SchXMLExportHelper()
{
    delete m_pImpl;
}

const OUString& SchXMLExportHelper::getChartCLSID()
{
	return m_pImpl->msCLSID;
}

UniReference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const
{
    return mxPropertySetMapper;
}

void SchXMLExportHelper_Impl::exportAutoStyles()
{
	if( mxExpPropMapper.is())
	{
		//ToDo: when embedded in calc/writer this is not necessary because the
		// numberformatter is shared between both documents
		mrExport.exportAutoDataStyles();

		// export chart auto styles
		mrAutoStylePool.exportXML(
			XML_STYLE_FAMILY_SCH_CHART_ID
			, mrExport.GetDocHandler(),
			mrExport.GetMM100UnitConverter(),
			mrExport.GetNamespaceMap()
            );

        // export auto styles for additional shapes
        mrExport.GetShapeExport()->exportAutoStyles();
        // and for text in additional shapes
        mrExport.GetTextParagraphExport()->exportTextAutoStyles();
	}
}

// private methods
// ---------------

SchXMLExportHelper_Impl::SchXMLExportHelper_Impl(
	SvXMLExport& rExport,
	SvXMLAutoStylePoolP& rASPool ) :
		mrExport( rExport ),
		mrAutoStylePool( rASPool ),
		mbHasSeriesLabels( sal_False ),
		mbHasCategoryLabels( sal_False ),
		mbRowSourceColumns( sal_True )
		// #110680#
		// this id depends on the ServiceManager used due to the binary filter stripping.
		// ,msCLSID( rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()))
{
	// #110680#
	// changed initialisation for msCLSID. Compare the ServiceInfo name with
	// the known name of the LegacyServiceManager.
	Reference<lang::XServiceInfo> xServiceInfo( mrExport.getServiceFactory(), uno::UNO_QUERY );
	DBG_ASSERT( xServiceInfo.is(), "XMultiServiceFactory without xServiceInfo (!)" );
	OUString rdbURL = xServiceInfo->getImplementationName();
	OUString implLegacyServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.office.LegacyServiceManager" ) );

	if( rdbURL.equals( implLegacyServiceManagerName ))
	{
		msCLSID = OUString( SvGlobalName( BF_SO3_SCH_CLASSID ).GetHexName());
	}
	else
	{
		msCLSID = OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
	}

	msTableName = OUString::createFromAscii( "local-table" );

	// create factory
	mxPropertyHandlerFactory = new XMLChartPropHdlFactory;

	if( mxPropertyHandlerFactory.is() )
	{
		// create property set mapper
		mxPropertySetMapper = new XMLChartPropertySetMapper;
	}

	mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport );

	// register chart auto-style family
	mrAutoStylePool.AddFamily(
		XML_STYLE_FAMILY_SCH_CHART_ID,
		OUString::createFromAscii( XML_STYLE_FAMILY_SCH_CHART_NAME ),
		mxExpPropMapper.get(),
		OUString::createFromAscii( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));

    // register shape family
	mrAutoStylePool.AddFamily(
		XML_STYLE_FAMILY_SD_GRAPHICS_ID,
		OUString::createFromAscii( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ),
		mxExpPropMapper.get(),
		OUString::createFromAscii( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX ));
    // register paragraph family also for shapes
	mrAutoStylePool.AddFamily(
		XML_STYLE_FAMILY_TEXT_PARAGRAPH,
        GetXMLToken( XML_PARAGRAPH ),
		mxExpPropMapper.get(),
        String( 'P' ));
    // register text family also for shapes
	mrAutoStylePool.AddFamily(
        XML_STYLE_FAMILY_TEXT_TEXT,
        GetXMLToken( XML_TEXT ),
		mxExpPropMapper.get(),
        String( 'T' ));
}

SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
{
}

void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
{
    parseDocument( rChartDoc, sal_False );
}

void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc,
									  sal_Bool bIncludeTable )
{
    parseDocument( rChartDoc, sal_True, bIncludeTable );
    DBG_ASSERT( maAutoStyleNameQueue.empty(), "There are still remaining autostyle names in the queue" );
}

::rtl::OUString lcl_GetStringFromNumberSequence( const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
{
    const sal_Int32* pArray = rSequenceMapping.getConstArray();
    const sal_Int32 nSize = rSequenceMapping.getLength();
    sal_Int32 i = 0;
    OUStringBuffer aBuf;
    bool bHasPredecessor = false;
    for( i = 0; i < nSize; ++i )
    {
        sal_Int32 nIndex = pArray[ i ];
        if( bRemoveOneFromEachIndex )
            --nIndex;
        if(nIndex>=0)
        {
            if(bHasPredecessor)
                aBuf.append( static_cast< sal_Unicode >( ' ' ));
            aBuf.append( nIndex, 10 );
            bHasPredecessor = true;
        }
    }
    return aBuf.makeStringAndClear();
}

/// if bExportContent is false the auto-styles are collected
void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc,
										sal_Bool bExportContent,
										sal_Bool bIncludeTable )
{
    Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
    if( !rChartDoc.is() || !xNewDoc.is() )
	{
		DBG_ERROR( "No XChartDocument was given for export." );
		return;
	}

    awt::Size aPageSize( getPageSize( xNewDoc ));
    if( bExportContent )
        addSize( aPageSize );
    Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
    Reference< chart2::XDiagram > xNewDiagram;
    if( xNewDoc.is())
        xNewDiagram.set( xNewDoc->getFirstDiagram());

    //todo remove if model changes are notified and view is updated automatically
    if( bExportContent )
    {
        Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
        if( xRefreshable.is() )
            xRefreshable->refresh();
    }

	// get Properties of ChartDocument
	sal_Bool bHasMainTitle = sal_False;
	sal_Bool bHasSubTitle = sal_False;
	sal_Bool bHasLegend = sal_False;
    util::DateTime aNullDate(0,0,0,0,30,12,1899);

    std::vector< XMLPropertyState > aPropertyStates;

	Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
	if( xDocPropSet.is())
	{
		try
		{
			Any aAny( xDocPropSet->getPropertyValue(
				OUString( RTL_CONSTASCII_USTRINGPARAM( "HasMainTitle" ))));
			aAny >>= bHasMainTitle;
			aAny = xDocPropSet->getPropertyValue(
				OUString( RTL_CONSTASCII_USTRINGPARAM( "HasSubTitle" )));
			aAny >>= bHasSubTitle;
			aAny = xDocPropSet->getPropertyValue(
				OUString( RTL_CONSTASCII_USTRINGPARAM( "HasLegend" )));
			aAny >>= bHasLegend;
            if ( bIncludeTable )
            {
                OUString sNullDate( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ));
                aAny = xDocPropSet->getPropertyValue(sNullDate);
                if ( !aAny.hasValue() )
                {
                    Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
                    if ( xChild.is() )
                    {
                        Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
                        if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName(sNullDate) )
                            aAny = xParentDoc->getPropertyValue(sNullDate);
                    }
                }

                aAny >>= aNullDate;
            }
		}
		catch( beans::UnknownPropertyException & )
		{
			DBG_WARNING( "Required property not found in ChartDocument" );
		}
	} // if( xDocPropSet.is())

    if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
    {
        SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, sal_True, sal_True );
        {
            ::rtl::OUStringBuffer sBuffer;
            SvXMLUnitConverter::convertDateTime(sBuffer,aNullDate);
            mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
            SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, sal_True, sal_True );
        }
    }

	// chart element
	// -------------

	SvXMLElementExport* pElChart = 0;
	// get property states for autostyles
	if( mxExpPropMapper.is())
	{
		Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
		if( xPropSet.is())
			aPropertyStates = mxExpPropMapper->Filter( xPropSet );
	}

	if( bExportContent )
	{
        //export data provider in xlink:href attribute
        const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
        if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
        {
            OUString aDataProviderURL( RTL_CONSTASCII_USTRINGPARAM( ".." ) );
            if( xNewDoc->hasInternalDataProvider() )
                aDataProviderURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) );
            else //special handling for data base data provider necessary
            {
                Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
                if( xDBDataProvider.is() )
                    aDataProviderURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) );
            }
            mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
            mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        }

        OUString sChartType( xDiagram->getDiagramType() );

		// attributes
		// determine class
		if( sChartType.getLength())
		{
			enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );

            DBG_ASSERT( eXMLChartType != XML_TOKEN_INVALID, "invalid chart class" );
            if( eXMLChartType == XML_TOKEN_INVALID )
                eXMLChartType = XML_BAR;

            if( eXMLChartType == XML_ADD_IN )
            {
                // sChartType is the servie-name of the add-in
				mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
                                       mrExport.GetNamespaceMap().GetQNameByKey(
                                           XML_NAMESPACE_OOO, sChartType) );
			}
            else if( eXMLChartType != XML_TOKEN_INVALID )
			{
				mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
						mrExport.GetNamespaceMap().GetQNameByKey(
							XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
			}

            //column-mapping or row-mapping
            if( maSequenceMapping.getLength() )
            {
                enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING;
                if( mbRowSourceColumns )
                    eTransToken = ::xmloff::token::XML_COLUMN_MAPPING;
                ::rtl::OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
                    maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );

                mrExport.AddAttribute( XML_NAMESPACE_CHART,
                                        ::xmloff::token::GetXMLToken( eTransToken ),
                                        aSequenceMappingStr );
            }
        }
		// write style name
        AddAutoStyleAttribute( aPropertyStates );

		//element
		pElChart = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, sal_True, sal_True );
	}
	else	// autostyles
	{
        CollectAutoStyle( aPropertyStates );
	}
	// remove property states for autostyles
	aPropertyStates.clear();

	// title element
	// -------------

	if( bHasMainTitle )
	{
		// get property states for autostyles
		if( mxExpPropMapper.is())
		{
			Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
			if( xPropSet.is())
				aPropertyStates = mxExpPropMapper->Filter( xPropSet );
		}
		if( bExportContent )
		{
			Reference< drawing::XShape > xShape = rChartDoc->getTitle();
			if( xShape.is())	// && "hasTitleBeenMoved"
				addPosition( xShape );

			// write style name
            AddAutoStyleAttribute( aPropertyStates );

			// element
			SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );

			// content (text:p)
			Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
			if( xPropSet.is())
			{
				Any aAny( xPropSet->getPropertyValue(
					OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
				OUString aText;
				aAny >>= aText;
                exportText( aText );
			}
		}
		else	// autostyles
		{
            CollectAutoStyle( aPropertyStates );
		}
		// remove property states for autostyles
		aPropertyStates.clear();
	}

	// subtitle element
	// ----------------

	if( bHasSubTitle )
	{
		// get property states for autostyles
		if( mxExpPropMapper.is())
		{
			Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
			if( xPropSet.is())
				aPropertyStates = mxExpPropMapper->Filter( xPropSet );
		}

		if( bExportContent )
		{
			Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
			if( xShape.is())
				addPosition( xShape );

			// write style name
            AddAutoStyleAttribute( aPropertyStates );

			// element (has no subelements)
			SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, sal_True, sal_True );

			// content (text:p)
			Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
			if( xPropSet.is())
			{
				Any aAny( xPropSet->getPropertyValue(
					OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
				OUString aText;
				aAny >>= aText;
                exportText( aText );
			}
		}
		else	// autostyles
		{
            CollectAutoStyle( aPropertyStates );
		}
		// remove property states for autostyles
		aPropertyStates.clear();
	}

	// legend element
	// --------------
	if( bHasLegend )
	{
		// get property states for autostyles
		if( mxExpPropMapper.is())
		{
			Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
			if( xPropSet.is())
				aPropertyStates = mxExpPropMapper->Filter( xPropSet );
		}

		if( bExportContent )
		{
			Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
			if( xProp.is())
			{
                // export legend anchor position
                try
				{
					Any aAny( xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Alignment" ))));
                    if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString );
				}
				catch( beans::UnknownPropertyException & )
				{
					DBG_WARNING( "Property Align not found in ChartLegend" );
				}

				// export absolute legend position
				Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
				addPosition( xLegendShape );

				// export legend size
                const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
                if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//do not export legend-expansion to ODF 1.0 and export size only if extensions are enabled //#i28670# todo: change this dependent on fileformat evolution
                {
                    try
				    {
                        chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
                        OUString aExpansionString;
					    Any aAny( xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Expansion" ))));
					    bool bHasExpansion = (aAny >>= nLegendExpansion);
                        if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
                        {
                            mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString );
                            if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
                            {
                                awt::Size aSize( xLegendShape->getSize() );
                                addSize( aSize, true );
                                rtl::OUStringBuffer aAspectRatioString;
                                SvXMLUnitConverter::convertDouble(aAspectRatioString, double(aSize.Width)/double(aSize.Height));
                                mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
                            }
                        }
				    }
				    catch( beans::UnknownPropertyException & )
				    {
					    DBG_WARNING( "Property Expansion not found in ChartLegend" );
				    }
                }
			}

			// write style name
            AddAutoStyleAttribute( aPropertyStates );

			// element
			SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, sal_True, sal_True );
		}
		else	// autostyles
		{
            CollectAutoStyle( aPropertyStates );
		}
		// remove property states for autostyles
		aPropertyStates.clear();
	}

	// plot-area element
	// -----------------
	if( xDiagram.is())
		exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );

    // export additional shapes
    // ------------------------
    if( xDocPropSet.is() )
    {
        if( bExportContent )
        {
            if( mxAdditionalShapes.is())
            {
                // can't call exportShapes with all shapes because the
                // initialisation happened with the complete draw page and not
                // the XShapes object used here. Thus the shapes have to be
                // exported one by one
                UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
                Reference< drawing::XShape > xShape;
                const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
                for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
                {
                    mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
                    DBG_ASSERT( xShape.is(), "Shape without an XShape?" );
                    if( ! xShape.is())
                        continue;

                    rShapeExport->exportShape( xShape );
                }
                // this would be the easier way if it worked:
                //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
            }
        }
        else
        {
            // get a sequence of non-chart shapes (inserted via clipboard)
            try
            {
                Any aShapesAny = xDocPropSet->getPropertyValue( OUString::createFromAscii( "AdditionalShapes" ));
                aShapesAny >>= mxAdditionalShapes;
            }
            catch( uno::Exception & rEx )
		    {
                (void)rEx; // avoid warning for pro build
                OSL_TRACE(
                    OUStringToOString(
                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "AdditionalShapes not found: " )) +
                        rEx.Message,
                        RTL_TEXTENCODING_ASCII_US ).getStr());
		    }

            if( mxAdditionalShapes.is())
            {
                // seek shapes has to be called for the whole page because in
                // the shape export the vector of shapes is accessed via the
                // ZOrder which might be (actually is) larger than the number of
                // shapes in mxAdditionalShapes
                Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
                DBG_ASSERT( xSupplier.is(), "Cannot retrieve draw page to initialize shape export" );
                if( xSupplier.is() )
                {
                    Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
                    DBG_ASSERT( xDrawPage.is(), "Invalid draw page for initializing shape export" );
                    if( xDrawPage.is())
                        mrExport.GetShapeExport()->seekShapes( xDrawPage );
                }

                // can't call collectShapesAutoStyles with all shapes because
                // the initialisation happened with the complete draw page and
                // not the XShapes object used here. Thus the shapes have to be
                // exported one by one
                UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
                Reference< drawing::XShape > xShape;
                const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
                for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
                {
                    mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
                    DBG_ASSERT( xShape.is(), "Shape without an XShape?" );
                    if( ! xShape.is())
                        continue;

                    rShapeExport->collectShapeAutoStyles( xShape );
                }
                // this would be the easier way if it worked:
                // mrExport.GetShapeExport()->collectShapesAutoStyles( mxAdditionalShapes );
            }
        }
    }

	// table element
	// (is included as subelement of chart)
	// ------------------------------------
	if( bExportContent )
	{
        // #85929# always export table, otherwise clipboard may loose data
        exportTable();
	}

	// close <chart:chart> element
	if( pElChart )
		delete pElChart;
}

void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
{
    sal_Int32 nLength = rComplexLabel.getLength();
    if( nLength<=1 )
        return;
    SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, sal_True, sal_True );
    for(sal_Int32 nN=0; nN<nLength; nN++)
    {
        SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, sal_True, sal_True );
        OUString aString;
        if( !(rComplexLabel[nN]>>=aString) )
        {
            //todo?
        }
        SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
    }
}

void SchXMLExportHelper_Impl::exportTable()
{
    // table element
	// -------------
	mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );

    try
    {
        bool bProtected = false;
        Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
        if ( ( xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ) ) >>= bProtected ) &&
             bProtected )
        {
            mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
        }
    }
    catch ( uno::Exception& )
    {
    }

    SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True );

    bool bHasOwnData = false;
    Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
    Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
    if( xNewDoc.is())
    {
        bHasOwnData = xNewDoc->hasInternalDataProvider();
        xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
    }

    Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
    {
        Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
        if( xChartDoc.is() )
            xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY );
    }

    if( bHasOwnData )
        lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
    lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
                                , xAnyDescriptionAccess, maCategoriesRange
                                , mbRowSourceColumns, xRangeConversion ));

    tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
    const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());

    tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
    const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());

    // declare columns
    {
        SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, sal_True, sal_True );
        SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
    }
    {
        SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, sal_True, sal_True );

        sal_Int32 nNextIndex = 0;
        for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ )
        {
            //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
            sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN];
            if( nHiddenIndex > nNextIndex )
            {
                sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
                if(nRepeat>1)
                    mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
                                   OUString::valueOf( nRepeat ));
                SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
            }
            mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
            SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
            nNextIndex = nHiddenIndex+1;
        }

        sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
        if( nEndIndex >= nNextIndex )
        {
            sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
            if(nRepeat>1)
                mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
                               OUString::valueOf( nRepeat ));
            SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
        }
    }

    // export rows with content
    //export header row
    {
        SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, sal_True, sal_True );
        SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );

        //first one empty cell for the row descriptions
        {
            SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
            SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True );
        }

        //export column descriptions
        tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
        const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
        const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
        sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
        sal_Int32 nC = 0;
        for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
             ; (aIt != aData.aColumnDescriptions.end())
             ; aIt++, nC++ )
        {
            bool bExportString = true;
            if( nC < nComplexCount )
            {
                const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
                if( rComplexLabel.getLength()>0 )
                {
                    double fValue=0.0;
                    if( rComplexLabel[0] >>=fValue )
                    {
                        bExportString = false;

                        SvXMLUnitConverter::convertDouble( msStringBuffer, fValue );
                        msString = msStringBuffer.makeStringAndClear();
                        mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
                        mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
                    }
                }
            }
            if( bExportString )
            {
                mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
            }

            SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
            exportText( *aIt );
            if( nC < nComplexCount )
                lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
            if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
            {
                // remind the original range to allow a correct re-association when copying via clipboard
                if ((*aColumnDescriptions_RangeIter).getLength())
                    SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
                ++aColumnDescriptions_RangeIter;
            }
        }
        OSL_ASSERT( bHasOwnData || aColumnDescriptions_RangeIter == aColumnDescriptions_RangeEnd );
    } // closing row and header-rows elements

    // export value rows
    {
        SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, sal_True, sal_True );
        tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
        const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
        sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
        sal_Int32 nC = 0;

        for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
            ; aRowIt != aData.aDataInRows.end()
            ; ++aRowIt, ++nC )
        {
            SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );

            //export row descriptions
            {
                bool bExportString = true;
                if( nC < nComplexCount )
                {
                    const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
                    if( rComplexLabel.getLength()>0 )
                    {
                        double fValue=0.0;
                        if( rComplexLabel[0] >>=fValue )
                        {
                            bExportString = false;

                            SvXMLUnitConverter::convertDouble( msStringBuffer, fValue );
                            msString = msStringBuffer.makeStringAndClear();
                            mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
                            mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
                        }
                    }
                }
                if( bExportString )
                {
                    mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
                }

                SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
                if( aRowDescriptionsIter != aData.aRowDescriptions.end())
                {
                    exportText( *aRowDescriptionsIter );
                    if( nC < nComplexCount )
                        lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
                    if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
                    {
                        // remind the original range to allow a correct re-association when copying via clipboard
                        SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
                        ++aRowDescriptions_RangeIter;
                    }
                    ++aRowDescriptionsIter;
                }
            }

            //export row values
            for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
                 aColIt != aRowIt->end(); ++aColIt )
            {
                SvXMLUnitConverter::convertDouble( msStringBuffer, *aColIt );
                msString = msStringBuffer.makeStringAndClear();
                mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
                mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
                SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
                exportText( msString, false ); // do not convert tabs and lfs
                if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
                    ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
                {
                    // remind the original range to allow a correct re-association when copying via clipboard
                    if ((*aDataRangeIter).getLength())
                        SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
                    ++aDataRangeIter;
                }
            }
        }
    }

    // if range iterator was used it should have reached its end
    OSL_ASSERT( bHasOwnData || (aDataRangeIter == aDataRangeEndIter) );
    OSL_ASSERT( bHasOwnData || (aRowDescriptions_RangeIter == aRowDescriptions_RangeEnd) );
}

namespace
{

Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
{
    Reference< chart2::XCoordinateSystem > xCooSys;
    Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
    if(xCooSysCnt.is())
    {
        Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
        if(aCooSysSeq.getLength()>0)
            xCooSys = aCooSysSeq[0];
    }
    return xCooSys;
}

Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
        enum XMLTokenEnum eDimension, bool bPrimary=true )
{
    Reference< chart2::XAxis > xNewAxis;
    try
    {
        if( xCooSys.is() )
        {
            sal_Int32 nDimensionIndex=0;
            switch( eDimension )
            {
            case XML_X:
                nDimensionIndex=0;
                break;
            case XML_Y:
                nDimensionIndex=1;
                break;
            case XML_Z:
                nDimensionIndex=2;
                break;
            default:
                break;
            }

            xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
        }
    }
    catch( const uno::Exception & )
    {
    }
    return xNewAxis;
}

}

void SchXMLExportHelper_Impl::exportPlotArea(
    Reference< chart::XDiagram > xDiagram,
    Reference< chart2::XDiagram > xNewDiagram,
    const awt::Size & rPageSize,
    sal_Bool bExportContent,
    sal_Bool bIncludeTable )
{
	DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" );
	if( ! xDiagram.is())
		return;

	// variables for autostyles
	Reference< beans::XPropertySet > xPropSet;
	std::vector< XMLPropertyState > aPropertyStates;

	sal_Bool bIs3DChart = sal_False;
	drawing::HomogenMatrix aTransMatrix;

    msStringBuffer.setLength( 0 );

    // plot-area element
	// -----------------

	SvXMLElementExport* pElPlotArea = 0;
	// get property states for autostyles
	xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY );
	if( xPropSet.is())
	{
		if( mxExpPropMapper.is())
			aPropertyStates = mxExpPropMapper->Filter( xPropSet );
	}
	if( bExportContent )
	{
		UniReference< XMLShapeExport > rShapeExport;

		// write style name
        AddAutoStyleAttribute( aPropertyStates );

        if( msChartAddress.getLength() )
        {
            if( !bIncludeTable )
                mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );

            Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
            if( xDoc.is() )
            {
                Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
                if( xDocProp.is())
                {
                    Any aAny;
                    sal_Bool bFirstCol = false, bFirstRow = false;

                    try
                    {
                        aAny = xDocProp->getPropertyValue(
                            OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstColumn" )));
                        aAny >>= bFirstCol;
                        aAny = xDocProp->getPropertyValue(
                            OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstRow" )));
                        aAny >>= bFirstRow;

                        if( bFirstCol || bFirstRow )
                        {
                            mrExport.AddAttribute( XML_NAMESPACE_CHART,
                                                   ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
                                                   ( bFirstCol
                                                     ? ( bFirstRow
                                                         ?  ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
                                                         :  ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
                                                     : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
                        }
                    }
                    catch( beans::UnknownPropertyException & )
                    {
                        DBG_ERRORFILE( "Properties missing" );
                    }
                }
            }
        }

        // #i72973#, #144135# only export table-number-list in OOo format (also for binary)
        Reference< beans::XPropertySet > xExportInfo( mrExport.getExportInfo());
        if( msTableNumberList.getLength() &&
            xExportInfo.is())
        {
            try
            {
                OUString sExportTableNumListPropName( RTL_CONSTASCII_USTRINGPARAM("ExportTableNumberList"));
                Reference< beans::XPropertySetInfo > xInfo( xExportInfo->getPropertySetInfo());
                bool bExportTableNumberList = false;
                if( xInfo.is() && xInfo->hasPropertyByName( sExportTableNumListPropName ) &&
                    (xExportInfo->getPropertyValue( sExportTableNumListPropName ) >>= bExportTableNumberList) &&
                    bExportTableNumberList )
                {
                    // this attribute is for charts embedded in calc documents only.
                    // With this you are able to store a file again in 5.0 binary format
                    mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_TABLE_NUMBER_LIST, msTableNumberList );
                }
            }
			catch( uno::Exception & rEx )
            {
#ifdef DBG_UTIL
                String aStr( rEx.Message );
                ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
                DBG_ERROR1( "chart:TableNumberList property caught: %s", aBStr.GetBuffer());
#else
                (void)rEx; // avoid warning
#endif
            }
        }

        // attributes
		Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
		if( xShape.is())
		{
			addPosition( xShape );
			addSize( xShape );
		}

		if( xPropSet.is())
		{
			Any aAny;

			// 3d attributes
			try
			{
				aAny = xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dim3D" )));
				aAny >>= bIs3DChart;

				if( bIs3DChart )
				{
					rShapeExport = mrExport.GetShapeExport();
					if( rShapeExport.is())
						rShapeExport->export3DSceneAttributes( xPropSet );
				}
			}
			catch( uno::Exception & rEx )
			{
#ifdef DBG_UTIL
                String aStr( rEx.Message );
                ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
                DBG_ERROR1( "chart:exportPlotAreaException caught: %s", aBStr.GetBuffer());
#else
                (void)rEx; // avoid warning
#endif
			}
		}

		// plot-area element
		pElPlotArea = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, sal_True, sal_True );

        //inner position rectangle element
        exportCoordinateRegion( xDiagram );

		// light sources (inside plot area element)
		if( bIs3DChart &&
			rShapeExport.is())
			rShapeExport->export3DLamps( xPropSet );
	}
	else	// autostyles
	{
        CollectAutoStyle( aPropertyStates );
	}
	// remove property states for autostyles
	aPropertyStates.clear();

    // axis elements
	// -------------
	exportAxes( xDiagram, xNewDiagram, bExportContent );

	// series elements
	// ---------------
    Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
    exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );

    // stock-chart elements
    OUString sChartType ( xDiagram->getDiagramType());
    if( 0 == sChartType.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.StockDiagram" )))
    {
        Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
        if( xStockPropProvider.is())
        {
            // stock-gain-marker
            Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
            if( xStockPropSet.is())
            {
                aPropertyStates.clear();
                aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );

                if( !aPropertyStates.empty() )
                {
                    if( bExportContent )
                    {
                        AddAutoStyleAttribute( aPropertyStates );

                        SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, sal_True, sal_True );
                    }
                    else
                    {
                        CollectAutoStyle( aPropertyStates );
                    }
                }
            }

            // stock-loss-marker
            xStockPropSet = xStockPropProvider->getDownBar();
            if( xStockPropSet.is())
            {
                aPropertyStates.clear();
                aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );

                if( !aPropertyStates.empty() )
                {
                    if( bExportContent )
                    {
                        AddAutoStyleAttribute( aPropertyStates );

                        SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, sal_True, sal_True );
                    }
                    else
                    {
                        CollectAutoStyle( aPropertyStates );
                    }
                }
            }

            // stock-range-line
            xStockPropSet = xStockPropProvider->getMinMaxLine();
            if( xStockPropSet.is())
            {
                aPropertyStates.clear();
                aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );

                if( !aPropertyStates.empty() )
                {
                    if( bExportContent )
                    {
                        AddAutoStyleAttribute( aPropertyStates );

                        SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, sal_True, sal_True );
                    }
                    else
                    {
                        CollectAutoStyle( aPropertyStates );
                    }
                }
            }
        }
    }

	// wall and floor element
	// ----------------------

	Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
	if( mxExpPropMapper.is() &&
		xWallFloorSupplier.is())
	{
		// remove property states for autostyles
		aPropertyStates.clear();

		Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
		if( xWallPropSet.is())
		{
			aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );

			if( !aPropertyStates.empty() )
			{
				// write element
				if( bExportContent )
				{
					// add style name attribute
                    AddAutoStyleAttribute( aPropertyStates );

					SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, sal_True, sal_True );
				}
				else	// autostyles
				{
                    CollectAutoStyle( aPropertyStates );
				}
			}
		}

        // floor element
        // -------------

		// remove property states for autostyles
		aPropertyStates.clear();

		Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
		if( xFloorPropSet.is())
		{
			aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );

			if( !aPropertyStates.empty() )
			{
				// write element
				if( bExportContent )
				{
					// add style name attribute
                    AddAutoStyleAttribute( aPropertyStates );

					SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, sal_True, sal_True );
				}
				else	// autostyles
				{
                    CollectAutoStyle( aPropertyStates );
				}
			}
		}
	}

	if( pElPlotArea )
		delete pElPlotArea;
}

void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
{
    const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
    if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
        return;
    if( nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST )//export only if extensions are enabled //#i100778# todo: change this dependent on fileformat evolution
        return;

    Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
    DBG_ASSERT( xDiaPos.is(), "Invalid xDiaPos as parameter" );
	if( !xDiaPos.is() )
		return;

    awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
    addPosition( awt::Point(aRect.X,aRect.Y) );
    addSize( awt::Size(aRect.Width,aRect.Height) );

    SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, sal_True, sal_True );//#i100778# todo: change to chart namespace in future - dependent on fileformat
}

namespace
{
    XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
    {
        XMLTokenEnum eToken = XML_DAYS;
        switch( nTimeUnit )
        {
        case ::com::sun::star::chart::TimeUnit::YEAR:
            eToken = XML_YEARS;
            break;
        case ::com::sun::star::chart::TimeUnit::MONTH:
            eToken = XML_MONTHS;
            break;
        default://days
            break;
        }
        return eToken;
    }
}

void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet > xAxisProps )
{
    if( !xAxisProps.is() )
        return;

    chart::TimeIncrement aIncrement;
    if( (xAxisProps->getPropertyValue( OUString::createFromAscii( "TimeIncrement" )) >>= aIncrement) )
    {
        sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY;
        if( aIncrement.TimeResolution >>= nTimeResolution )
            mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );

        OUStringBuffer aValue;
        chart::TimeInterval aInterval;
        if( aIncrement.MajorTimeInterval >>= aInterval )
        {
            SvXMLUnitConverter::convertNumber( aValue, aInterval.Number );
            mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
            mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
        }
        if( aIncrement.MinorTimeInterval >>= aInterval )
        {
            SvXMLUnitConverter::convertNumber( aValue, aInterval.Number );
            mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
            mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
        }

        SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, sal_True, sal_True );//#i25706#todo: change namespace for next ODF version
    }
}

void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent )
{
    if( !xTitleProps.is() )
        return;
    std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xTitleProps );
    if( bExportContent )
    {
        OUString aText;
        Any aAny( xTitleProps->getPropertyValue(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
        aAny >>= aText;

        Reference< drawing::XShape > xShape( xTitleProps, uno::UNO_QUERY );
        if( xShape.is())
            addPosition( xShape );

        AddAutoStyleAttribute( aPropertyStates );
        SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );

        // paragraph containing title
        exportText( aText );
    }
    else
    {
        CollectAutoStyle( aPropertyStates );
    }
    aPropertyStates.clear();
}

void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent )
{
    if( !xGridProperties.is() )
        return;
    std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xGridProperties );
    if( bExportContent )
    {
        AddAutoStyleAttribute( aPropertyStates );
        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
        SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, sal_True, sal_True );
    }
    else
    {
        CollectAutoStyle( aPropertyStates );
    }
    aPropertyStates.clear();
}

namespace
{

//returns true if a date scale needs to be exported
bool lcl_exportAxisType( const Reference< chart2::XAxis > xChart2Axis, SvXMLExport& rExport)
{
    bool bExportDateScale = false;
    if( !xChart2Axis.is() )
        return bExportDateScale;

    const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
    if( nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST ) //#i25706#todo: change version for next ODF version
        return bExportDateScale;

    chart2::ScaleData aScale( xChart2Axis->getScaleData() );
    //#i25706#todo: change namespace for next ODF version
    sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;

    switch(aScale.AxisType)
    {
    case chart2::AxisType::CATEGORY:
        if( aScale.AutoDateAxis )
        {
            rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
            bExportDateScale = true;
        }
        else
            rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
        break;
    case chart2::AxisType::DATE:
        rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
        bExportDateScale = true;
        break;
    default: //AUTOMATIC
        rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
        break;
    }

    return bExportDateScale;
}

}

void SchXMLExportHelper_Impl::exportAxis(
    enum XMLTokenEnum eDimension,
    enum XMLTokenEnum eAxisName,
    const Reference< beans::XPropertySet > xAxisProps,
    const Reference< chart2::XAxis >& xChart2Axis,
    const OUString& rCategoriesRange,
    bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
    bool bExportContent )
{
    static const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
    std::vector< XMLPropertyState > aPropertyStates;
    SvXMLElementExport* pAxis = NULL;

    // get property states for autostyles
    if( xAxisProps.is() && mxExpPropMapper.is() )
    {
        lcl_exportNumberFormat( sNumFormat, xAxisProps, mrExport );
        aPropertyStates = mxExpPropMapper->Filter( xAxisProps );
    }

    bool bExportDateScale = false;
    if( bExportContent )
    {
        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
        AddAutoStyleAttribute( aPropertyStates ); // write style name
        if( rCategoriesRange.getLength() )
            bExportDateScale = lcl_exportAxisType( xChart2Axis, mrExport );

        // open axis element
        pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, sal_True, sal_True );
    }
    else
    {
        CollectAutoStyle( aPropertyStates );
    }
    aPropertyStates.clear();

    //date scale
    if( bExportDateScale )
        exportDateScale( xAxisProps );

    Reference< beans::XPropertySet > xTitleProps;
    Reference< beans::XPropertySet > xMajorGridProps;
    Reference< beans::XPropertySet > xMinorGridProps;
    Reference< chart::XAxis > xAxis( xAxisProps, uno::UNO_QUERY );
    if( xAxis.is() )
    {
        xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0;
        xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0;
        xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0;
    }

    // axis-title
    exportAxisTitle( xTitleProps , bExportContent );

    // categories if we have a categories chart
    if( bExportContent && rCategoriesRange.getLength() )
    {
        mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
        SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, sal_True, sal_True );
    }

    // grid
    exportGrid( xMajorGridProps, true, bExportContent );
    exportGrid( xMinorGridProps, false, bExportContent );

    if( pAxis )
    {
        //close axis element
        delete pAxis;
        pAxis = NULL;
    }
}

void SchXMLExportHelper_Impl::exportAxes(
    const Reference< chart::XDiagram > & xDiagram,
    const Reference< chart2::XDiagram > & xNewDiagram,
    sal_Bool bExportContent )
{
	DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" );
	if( ! xDiagram.is())
		return;

	// get some properties from document first
	sal_Bool bHasXAxis = sal_False,
		bHasYAxis = sal_False,
		bHasZAxis = sal_False,
		bHasSecondaryXAxis = sal_False,
		bHasSecondaryYAxis = sal_False;
	sal_Bool bHasXAxisTitle = sal_False,
		bHasYAxisTitle = sal_False,
		bHasZAxisTitle = sal_False,
		bHasSecondaryXAxisTitle = sal_False,
		bHasSecondaryYAxisTitle = sal_False;
	sal_Bool bHasXAxisMajorGrid = sal_False,
		bHasXAxisMinorGrid = sal_False,
		bHasYAxisMajorGrid = sal_False,
		bHasYAxisMinorGrid = sal_False,
		bHasZAxisMajorGrid = sal_False,
		bHasZAxisMinorGrid = sal_False;

    // get multiple properties using XMultiPropertySet
	MultiPropertySetHandler	aDiagramProperties (xDiagram);

	aDiagramProperties.Add (
		OUString(RTL_CONSTASCII_USTRINGPARAM("HasXAxis")), bHasXAxis);
	aDiagramProperties.Add (
		OUString(RTL_CONSTASCII_USTRINGPARAM("HasYAxis")), bHasYAxis);
	aDiagramProperties.Add (
		OUString(RTL_CONSTASCII_USTRINGPARAM("HasZAxis")), bHasZAxis);
	aDiagramProperties.Add (
		OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryXAxis")), bHasSecondaryXAxis);
	aDiagramProperties.Add (
		OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryYAxis")), bHasSecondaryYAxis);

	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisTitle")), bHasXAxisTitle);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisTitle")), bHasYAxisTitle);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisTitle")), bHasZAxisTitle);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryXAxisTitle")), bHasSecondaryXAxisTitle);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryYAxisTitle")), bHasSecondaryYAxisTitle);

	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisGrid")), bHasXAxisMajorGrid);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisGrid")), bHasYAxisMajorGrid);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisGrid")), bHasZAxisMajorGrid);

	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisHelpGrid")), bHasXAxisMinorGrid);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisHelpGrid")), bHasYAxisMinorGrid);
	aDiagramProperties.Add (
		OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisHelpGrid")), bHasZAxisMinorGrid);

    if ( ! aDiagramProperties.GetProperties ())
    {
        DBG_WARNING ("Required properties not found in Chart diagram");
    }

    Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );

    // write an axis element also if the axis itself is not visible, but a grid or a title

    OUString aCategoriesRange;
    Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );

    // x axis
	// -------
    Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
    if( xNewAxis.is() )
    {
        Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY );
        if( mbHasCategoryLabels && bExportContent )
        {
            Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
            if( xCategories.is() )
            {
                Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
                if( xValues.is() )
                {
                    Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
                    maCategoriesRange = xValues->getSourceRangeRepresentation();
                    aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
                }
            }
        }
        exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
        aCategoriesRange = OUString();
    }

    // secondary x axis
    // -------
    Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
    xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
    if( xNewAxis.is() )
    {
        Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY );
        exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
    }

	// y axis
	// -------
    xNewAxis = lcl_getAxis( xCooSys, XML_Y );
    if( xNewAxis.is() )
    {
        Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY );
        exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
    }

    // secondary y axis
    // -------
    xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
    if( xNewAxis.is() )
    {
        Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY );
        exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
    }

	// z axis
	// -------
    xNewAxis = lcl_getAxis( xCooSys, XML_Z );
    if( xNewAxis.is() )
    {
        Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY );
        exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
    }
}

namespace
{
    bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
    {
        if( !xDataSequence.is() )
            return false;//have no data

        Sequence< uno::Any > aData;
        Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
        if( xNumericalDataSequence.is() )
        {
            Sequence< double >  aDoubles( xNumericalDataSequence->getNumericalData() );
            sal_Int32 nCount = aDoubles.getLength();
            for( sal_Int32 i = 0; i < nCount; ++i )
            {
                if( !::rtl::math::isNan( aDoubles[i] ) )
                    return false;//have double value
            }
        }
        else
        {
            aData = xDataSequence->getData();
            double fDouble = 0.0;
            sal_Int32 nCount = aData.getLength();
            for( sal_Int32 i = 0; i < nCount; ++i )
            {
                if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
                    return false;//have double value
            }

        }
        //no values found

        Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
        if( xTextualDataSequence.is() )
        {
            uno::Sequence< rtl::OUString > aStrings( xTextualDataSequence->getTextualData() );
            sal_Int32 nCount = aStrings.getLength();
            for( sal_Int32 i = 0; i < nCount; ++i )
            {
                if( aStrings[i].getLength() )
                    return true;//have text
            }
        }
        else
        {
            if( !aData.getLength() )
                aData = xDataSequence->getData();
            uno::Any aAny;
            OUString aString;
            sal_Int32 nCount = aData.getLength();
            for( sal_Int32 i = 0; i < nCount; ++i )
            {
                if( (aData[i]>>=aString) && aString.getLength() )
                    return true;//have text
            }
        }
        //no doubles and no texts
        return false;
    }
}

void SchXMLExportHelper_Impl::exportSeries(
    const Reference< chart2::XDiagram > & xNewDiagram,
    const awt::Size & rPageSize,
    sal_Bool bExportContent,
    sal_Bool bHasTwoYAxes )
{
    Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
    if( ! xBCooSysCnt.is())
        return;
    Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );

    OUString aFirstXDomainRange;
    OUString aFirstYDomainRange;

	std::vector< XMLPropertyState > aPropertyStates;

    const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
    const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" ));

    Sequence< Reference< chart2::XCoordinateSystem > >
        aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
    for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
    {
        Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
        if( ! xCTCnt.is())
            continue;
        Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
        for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
        {
            Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
            if( ! xDSCnt.is())
                continue;
            // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
            OUString aChartType( aCTSeq[nCTIdx]->getChartType());
            OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();

            // special export for stock charts
            if( aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType")))
            {
                sal_Bool bJapaneseCandleSticks = sal_False;
                Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
                if( xCTProp.is())
                    xCTProp->getPropertyValue( OUString::createFromAscii("Japanese")) >>= bJapaneseCandleSticks;
                exportCandleStickSeries(
                    xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
                continue;
            }

            // export dataseries for current chart-type
            Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
            for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
            {
                // export series
                Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
                if( xSource.is())
                {
                    SvXMLElementExport* pSeries = NULL;
                    Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
                        xSource->getDataSequences());
                    sal_Int32 nMainSequenceIndex = -1;
                    sal_Int32 nSeriesLength = 0;
                    sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
                    sal_Bool bHasMeanValueLine = false;
                    chart::ChartRegressionCurveType eRegressionType( chart::ChartRegressionCurveType_NONE );
                    chart::ChartErrorIndicatorType eErrorType( chart::ChartErrorIndicatorType_NONE );
                    sal_Int32 nErrorBarStyle( chart::ErrorBarStyle::NONE );
                    Reference< beans::XPropertySet > xPropSet;
                    tLabelValuesDataPair aSeriesLabelValuesPair;

                    // search for main sequence and create a series element
                    {
                        Reference< chart2::data::XDataSequence > xValuesSeq;
                        Reference< chart2::data::XDataSequence > xLabelSeq;
                        sal_Int32 nSeqIdx=0;
                        for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
                        {
                            OUString aRole;
                            Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
                            if( nMainSequenceIndex==-1 )
                            {
                                Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
                                if( xSeqProp.is())
                                    xSeqProp->getPropertyValue(OUString::createFromAscii("Role")) >>= aRole;
                                // "main" sequence
                                if( aRole.equals( aLabelRole ))
                                {
                                    xValuesSeq.set( xTempValueSeq );
                                    xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
                                    nMainSequenceIndex = nSeqIdx;
                                }
                            }
                            sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
                            if( nSeriesLength < nSequenceLength )
                                nSeriesLength = nSequenceLength;
                        }

                        // have found the main sequence, then xValuesSeq and
                        // xLabelSeq contain those.  Otherwise both are empty
                        {
                            // get property states for autostyles
                            try
                            {
                                xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
                                    aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
                            }
                            catch( uno::Exception & rEx )
                            {
                                (void)rEx; // avoid warning for pro build
                                OSL_TRACE(
                                    OUStringToOString(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                                      "Series not found or no XPropertySet: " )) +
                                        rEx.Message,
                                        RTL_TEXTENCODING_ASCII_US ).getStr());
                                continue;
                            }
                            if( xPropSet.is())
                            {
                                // determine attached axis
                                try
                                {
                                    Any aAny( xPropSet->getPropertyValue(
                                                  OUString( RTL_CONSTASCII_USTRINGPARAM( "Axis" ))));
                                    aAny >>= nAttachedAxis;

                                    aAny = xPropSet->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM ( "MeanValue" )));
                                    aAny >>= bHasMeanValueLine;

                                    aAny = xPropSet->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM( "RegressionCurves" )));
                                    aAny >>= eRegressionType;

                                    aAny = xPropSet->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorIndicator" )));
                                    aAny >>= eErrorType;

                                    aAny = xPropSet->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorBarStyle" )));
                                    aAny >>= nErrorBarStyle;
                                }
                                catch( beans::UnknownPropertyException & rEx )
                                {
                                    (void)rEx; // avoid warning for pro build
                                    OSL_TRACE(
                                        OUStringToOString(
                                            OUString( RTL_CONSTASCII_USTRINGPARAM(
                                                          "Required property not found in DataRowProperties: " )) +
                                            rEx.Message,
                                            RTL_TEXTENCODING_ASCII_US ).getStr());
                                }

                                const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
                                if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
                                {
                                    lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
                                    lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
                                }

                                if( mxExpPropMapper.is())
                                    aPropertyStates = mxExpPropMapper->Filter( xPropSet );
                            }

                            if( bExportContent )
                            {
                                if( bHasTwoYAxes )
                                {
                                    if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
                                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
                                    else
                                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
                                }

                                // write style name
                                AddAutoStyleAttribute( aPropertyStates );

                                if( xValuesSeq.is())
                                    mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
                                                           lcl_ConvertRange(
                                                               xValuesSeq->getSourceRangeRepresentation(),
                                                               xNewDoc ));
                                else
                                    // #i75297# allow empty series, export empty range to have all ranges on import
                                    mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());

                                if( xLabelSeq.is())
                                    mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS,
                                                           lcl_ConvertRange(
                                                               xLabelSeq->getSourceRangeRepresentation(),
                                                               xNewDoc ));
                                if( xLabelSeq.is() || xValuesSeq.is() )
                                    aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );

                                // chart-type for mixed types
                                enum XMLTokenEnum eCTToken(
                                    SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
                                //@todo: get token for current charttype
                                mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
                                                       mrExport.GetNamespaceMap().GetQNameByKey(
                                                           XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));

                                // open series element until end of for loop
                                pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
                            }
                            else	// autostyles
                            {
                                CollectAutoStyle( aPropertyStates );
                            }
                            // remove property states for autostyles
                            aPropertyStates.clear();
                        }
                    }

                    // export domain elements if we have a series parent element
                    if( pSeries )
                    {
                        // domain elements
                        if( bExportContent )
                        {
                            bool bIsScatterChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.ScatterChartType"));
                            bool bIsBubbleChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.BubbleChartType"));
                            Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
                            if( bIsBubbleChart )
                            {
                                Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-y" ) ) );
                                if( xSequence.is() )
                                {
                                    xYValuesForBubbleChart = xSequence->getValues();
                                    if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
                                        xYValuesForBubbleChart = 0;
                                }
                            }
                            if( bIsScatterChart || bIsBubbleChart )
                            {
                                Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-x" ) ) );
                                if( xSequence.is() )
                                {
                                    Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
                                    if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
                                        m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xValues ));
                                }
                                else if( nSeriesIdx==0 )
                                {
                                    //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
                                    Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
                                    if( xCategories.is() )
                                    {
                                        Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
                                        if( !lcl_hasNoValuesButText( xValues ) )
                                            lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
                                    }
                                }
                            }
                            if( xYValuesForBubbleChart.is() )
                                m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xYValuesForBubbleChart ));
                        }
                    }

                    // add sequences for main sequence after domain sequences,
                    // so that the export of the local table has the correct order
                    if( bExportContent &&
                        (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
                        m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );

                    // statistical objects:
                    // regression curves and mean value lines
                    if( bHasMeanValueLine &&
                        xPropSet.is() &&
                        mxExpPropMapper.is() )
                    {
                        Reference< beans::XPropertySet > xStatProp;
                        try
                        {
                            Any aPropAny( xPropSet->getPropertyValue(
                                            OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMeanValueProperties" ))));
                            aPropAny >>= xStatProp;
                        }
                        catch( uno::Exception & rEx )
                        {
                            (void)rEx; // avoid warning for pro build
                            DBG_ERROR1( "Exception caught during Export of series - optional DataMeanValueProperties not available: %s",
                                        OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
                        }

                        if( xStatProp.is() )
                        {
                            aPropertyStates = mxExpPropMapper->Filter( xStatProp );

                            if( !aPropertyStates.empty() )
                            {
                                // write element
                                if( bExportContent )
                                {
                                    // add style name attribute
                                    AddAutoStyleAttribute( aPropertyStates );

                                    SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, sal_True, sal_True );
                                }
                                else	// autostyles
                                {
                                    CollectAutoStyle( aPropertyStates );
                                }
                            }
                        }
                    }

                    if( eRegressionType != chart::ChartRegressionCurveType_NONE &&
                        xPropSet.is() &&
                        mxExpPropMapper.is() )
                    {
                        exportRegressionCurve( aSeriesSeq[nSeriesIdx], xPropSet, rPageSize, bExportContent );
                    }

                    if( nErrorBarStyle != chart::ErrorBarStyle::NONE &&
                        eErrorType != chart::ChartErrorIndicatorType_NONE &&
                        xPropSet.is() &&
                        mxExpPropMapper.is() )
                    {
                        Reference< beans::XPropertySet > xStatProp;
                        try
                        {
                            Any aPropAny( xPropSet->getPropertyValue(
                                            OUString( RTL_CONSTASCII_USTRINGPARAM( "DataErrorProperties" ))));
                            aPropAny >>= xStatProp;
                        }
                        catch( uno::Exception & rEx )
                        {
                            (void)rEx; // avoid warning for pro build
                            DBG_ERROR1( "Exception caught during Export of series - optional DataErrorProperties not available: %s",
                                        OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
                        }

                        if( xStatProp.is() )
                        {
                            if( bExportContent &&
                                nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
                            {
                                // register data ranges for error bars for export in local table
                                ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
                                    lcl_getErrorBarSequences( xStatProp ));
                                for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt(
                                         aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt )
                                {
                                    m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, *aIt ));
                                }
                            }

                            aPropertyStates = mxExpPropMapper->Filter( xStatProp );

                            if( !aPropertyStates.empty() )
                            {
                                // write element
                                if( bExportContent )
                                {
                                    // add style name attribute
                                    AddAutoStyleAttribute( aPropertyStates );

                                    const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
                                    if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 )
                                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, XML_Y );//#i114149#
                                    SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, sal_True, sal_True );
                                }
                                else	// autostyles
                                {
                                    CollectAutoStyle( aPropertyStates );
                                }
                            }
                        }
                    }

                    exportDataPoints(
                        uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
                        nSeriesLength, xNewDiagram, bExportContent );

                    // close series element
                    if( pSeries )
                        delete pSeries;
                }
            }
            aPropertyStates.clear();
        }
    }
}

void SchXMLExportHelper_Impl::exportRegressionCurve(
    const Reference< chart2::XDataSeries > & xSeries,
    const Reference< beans::XPropertySet > & xSeriesProp,
    const awt::Size & rPageSize,
    sal_Bool bExportContent )
{
    OSL_ASSERT( mxExpPropMapper.is());

	std::vector< XMLPropertyState > aPropertyStates;
	std::vector< XMLPropertyState > aEquationPropertyStates;
    Reference< beans::XPropertySet > xStatProp;
    try
    {
        Any aPropAny( xSeriesProp->getPropertyValue(
                          OUString( RTL_CONSTASCII_USTRINGPARAM( "DataRegressionProperties" ))));
        aPropAny >>= xStatProp;
    }
    catch( uno::Exception & rEx )
    {
        (void)rEx; // avoid warning for pro build
        DBG_ERROR1( "Exception caught during Export of series - optional DataRegressionProperties not available: %s",
                    OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
    }

    if( xStatProp.is() )
    {
        Reference< chart2::XRegressionCurve > xRegCurve( SchXMLTools::getRegressionCurve( xSeries ));
        Reference< beans::XPropertySet > xEquationProperties;
        if( xRegCurve.is())
            xEquationProperties.set( xRegCurve->getEquationProperties());

        bool bShowEquation = false;
        bool bShowRSquared = false;
        bool bExportEquation = false;
        aPropertyStates = mxExpPropMapper->Filter( xStatProp );
        if( xEquationProperties.is())
        {
            xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowEquation" )))
                >>= bShowEquation;
            xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowCorrelationCoefficient" )))
                >>= bShowRSquared;
            bExportEquation = ( bShowEquation || bShowRSquared );
            const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
            if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
                bExportEquation=false;
            if( bExportEquation )
            {
                // number format
                sal_Int32 nNumberFormat = 0;
                if( ( xEquationProperties->getPropertyValue(
                          OUString( RTL_CONSTASCII_USTRINGPARAM( "NumberFormat" ))) >>= nNumberFormat ) &&
                    nNumberFormat != -1 )
                {
                    mrExport.addDataStyle( nNumberFormat );
                }
                aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
            }
        }

        if( !aPropertyStates.empty() || bExportEquation )
        {
            // write element
            if( bExportContent )
            {
                // add style name attribute
                if( !aPropertyStates.empty())
                    AddAutoStyleAttribute( aPropertyStates );
                SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, sal_True, sal_True );
                if( bExportEquation )
                {
                    // default is true
                    if( !bShowEquation )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, XML_FALSE );
                    // default is false
                    if( bShowRSquared )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, XML_TRUE );

                    // export position
                    chart2::RelativePosition aRelativePosition;
                    if( xEquationProperties->getPropertyValue(
                            OUString( RTL_CONSTASCII_USTRINGPARAM("RelativePosition"))) >>= aRelativePosition )
                    {
                        double fX = aRelativePosition.Primary * rPageSize.Width;
                        double fY = aRelativePosition.Secondary * rPageSize.Height;
                        awt::Point aPos;
                        aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
                        aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
                        addPosition( aPos );
                    }

                    if( !aEquationPropertyStates.empty())
                        AddAutoStyleAttribute( aEquationPropertyStates );

                    SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, sal_True, sal_True );
                }
            }
            else	// autostyles
            {
                if( !aPropertyStates.empty())
                    CollectAutoStyle( aPropertyStates );
                if( bExportEquation && !aEquationPropertyStates.empty())
                    CollectAutoStyle( aEquationPropertyStates );
            }
        }
    }
}

void SchXMLExportHelper_Impl::exportCandleStickSeries(
    const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
    const Reference< chart2::XDiagram > & xDiagram,
    sal_Bool bJapaneseCandleSticks,
    sal_Bool bExportContent )
{
// 	std::vector< XMLPropertyState > aPropertyStates;

    for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
    {
        Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
        sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
            ? chart::ChartAxisAssign::PRIMARY_Y
            : chart::ChartAxisAssign::SECONDARY_Y;

        Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
        if( xSource.is())
        {
            // export series in correct order (as we don't store roles)
            // with japanese candlesticks: open, low, high, close
            // otherwise: low, high, close
            Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
                xSource->getDataSequences());

            sal_Int32 nSeriesLength =
                lcl_getSequenceLengthByRole( aSeqCnt, OUString::createFromAscii("values-last"));

            if( bExportContent )
            {
                Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
                //@todo: export data points

                // open
                if( bJapaneseCandleSticks )
                {
                    tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
                        aSeqCnt, OUString::createFromAscii("values-first"),  xNewDoc, m_aDataSequencesToExport ));
                    if( aRanges.second.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
                    if( aRanges.first.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
                    if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
                    else
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
                    SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
                    // export empty data points
                    exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
                }

                // low
                {
                    tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
                        aSeqCnt, OUString::createFromAscii("values-min"),  xNewDoc, m_aDataSequencesToExport ));
                    if( aRanges.second.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
                    if( aRanges.first.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
                    if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
                    else
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
                    SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
                    // export empty data points
                    exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
                }

                // high
                {
                    tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
                        aSeqCnt, OUString::createFromAscii("values-max"),  xNewDoc, m_aDataSequencesToExport ));
                    if( aRanges.second.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
                    if( aRanges.first.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
                    if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
                    else
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
                    SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
                    // export empty data points
                    exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
                }

                // close
                {
                    tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
                        aSeqCnt, OUString::createFromAscii("values-last"),  xNewDoc, m_aDataSequencesToExport ));
                    if( aRanges.second.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
                    if( aRanges.first.getLength())
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
                    if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
                    else
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
                    // write style name
//                     AddAutoStyleAttribute( aPropertyStates );
                    // chart type
//                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
//                                            mrExport.GetNamespaceMap().GetQNameByKey(
//                                                XML_NAMESPACE_CHART, GetXMLToken( XML_STOCK )));
                    SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
                    // export empty data points
                    exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
                }
            }
            else	// autostyles
            {
                // for close series
//                 CollectAutoStyle( aPropertyStates );
            }
            // remove property states for autostyles
//             aPropertyStates.clear();
        }
    }
}

void SchXMLExportHelper_Impl::exportDataPoints(
    const uno::Reference< beans::XPropertySet > & xSeriesProperties,
    sal_Int32 nSeriesLength,
    const uno::Reference< chart2::XDiagram > & xDiagram,
    sal_Bool bExportContent )
{
    // data-points
    // -----------
    // write data-points only if they contain autostyles
    // objects with equal autostyles are grouped using the attribute
    // repeat="number"

    // Note: if only the nth data-point has autostyles there is an element
    // without style and repeat="n-1" attribute written in advance.

    // the sequence aDataPointSeq contains indices of data-points that
    // do have own attributes.  This increases the performance substantially.

    // more performant version for #93600#
    if( mxExpPropMapper.is())
    {
        uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );

        std::vector< XMLPropertyState > aPropertyStates;

        const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
        const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" ));

        bool bVaryColorsByPoint = false;
        Sequence< sal_Int32 > aDataPointSeq;
        if( xSeriesProperties.is())
        {
            Any aAny = xSeriesProperties->getPropertyValue(
                OUString( RTL_CONSTASCII_USTRINGPARAM( "AttributedDataPoints" )));
            aAny >>= aDataPointSeq;
            xSeriesProperties->getPropertyValue(
                OUString( RTL_CONSTASCII_USTRINGPARAM( "VaryColorsByPoint" ))) >>= bVaryColorsByPoint;
        }


        sal_Int32 nSize = aDataPointSeq.getLength();
        DBG_ASSERT( nSize <= nSeriesLength, "Too many point attributes" );

        const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
        sal_Int32 nElement;
        sal_Int32 nRepeat;
        Reference< chart2::XColorScheme > xColorScheme;
        if( xDiagram.is())
            xColorScheme.set( xDiagram->getDefaultColorScheme());

        ::std::list< SchXMLDataPointStruct > aDataPointList;

        sal_Int32 nLastIndex = -1;
        sal_Int32 nCurrIndex = 0;

        // collect elements
        if( bVaryColorsByPoint && xColorScheme.is() )
        {
            ::std::set< sal_Int32 > aAttrPointSet;
            ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
                            ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
            const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
            for( nElement = 0; nElement < nSeriesLength; ++nElement )
            {
                aPropertyStates.clear();
                uno::Reference< beans::XPropertySet > xPropSet;
                bool bExportNumFmt = false;
                if( aAttrPointSet.find( nElement ) != aEndIt )
                {
                    try
                    {
                        xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
                                    xSeries, nElement, mrExport.GetModel() );
                        bExportNumFmt = true;
                    }
                    catch( uno::Exception & rEx )
                    {
                        (void)rEx; // avoid warning for pro build
                        DBG_ERROR1( "Exception caught during Export of data point: %s",
                                    OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
                    }
                }
                else
                {
                    // property set only containing the color
                    xPropSet.set( new ::xmloff::chart::ColorPropertySet(
                                        xColorScheme->getColorByIndex( nElement )));
                }
                DBG_ASSERT( xPropSet.is(), "Pie Segments should have properties" );
                if( xPropSet.is())
                {
                    const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
                    if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
                    {
                        lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
                        lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
                    }

                    aPropertyStates = mxExpPropMapper->Filter( xPropSet );
                    if( !aPropertyStates.empty() )
                    {
                        if( bExportContent )
                        {
                            // write data-point with style
                            DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );

                            SchXMLDataPointStruct aPoint;
                            aPoint.maStyleName = maAutoStyleNameQueue.front();
                            maAutoStyleNameQueue.pop();
                            aDataPointList.push_back( aPoint );
                        }
                        else
                        {
                            CollectAutoStyle( aPropertyStates );
                        }
                    }
                }
            }
            DBG_ASSERT( !bExportContent || (static_cast<sal_Int32>(aDataPointList.size()) == nSeriesLength),
                        "not enough data points on content export" );
        }
        else
        {
            for( nElement = 0; nElement < nSize; ++nElement )
            {
                aPropertyStates.clear();
                nCurrIndex = pPoints[ nElement ];
                //assuming sorted indices in pPoints

                if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
                    break;

                // write leading empty data points
                if( nCurrIndex - nLastIndex > 1 )
                {
                    SchXMLDataPointStruct aPoint;
                    aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
                    aDataPointList.push_back( aPoint );
                }

                uno::Reference< beans::XPropertySet > xPropSet;
                // get property states
                try
                {
                    xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
                                    xSeries, nCurrIndex, mrExport.GetModel() );
                }
                catch( uno::Exception & rEx )
                {
                    (void)rEx; // avoid warning for pro build
                    DBG_ERROR1( "Exception caught during Export of data point: %s",
                                OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
                }
                if( xPropSet.is())
                {
                    const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
                    if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
                    {
                        lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
                        lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
                    }

                    aPropertyStates = mxExpPropMapper->Filter( xPropSet );
                    if( !aPropertyStates.empty() )
                    {
                        if( bExportContent )
                        {
                            // write data-point with style
                            DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
                            SchXMLDataPointStruct aPoint;
                            aPoint.maStyleName = maAutoStyleNameQueue.front();
                            maAutoStyleNameQueue.pop();

                            aDataPointList.push_back( aPoint );
                            nLastIndex = nCurrIndex;
                        }
                        else
                        {
                            CollectAutoStyle( aPropertyStates );
                        }
                        continue;
                    }
                }

                // if we get here the property states are empty
                SchXMLDataPointStruct aPoint;
                aDataPointList.push_back( aPoint );

                nLastIndex = nCurrIndex;
            }
            // final empty elements
            nRepeat = nSeriesLength - nLastIndex - 1;
            if( nRepeat > 0 )
            {
                SchXMLDataPointStruct aPoint;
                aPoint.mnRepeat = nRepeat;
                aDataPointList.push_back( aPoint );
            }
        }

        if( bExportContent )
        {
            // write elements (merge equal ones)
            ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
            SchXMLDataPointStruct aPoint;
            SchXMLDataPointStruct aLastPoint;

            // initialize so that it doesn't matter if
            // the element is counted in the first iteration
            aLastPoint.mnRepeat = 0;

            for( ; aIter != aDataPointList.end(); ++aIter )
            {
                aPoint = (*aIter);

                if( aPoint.maStyleName == aLastPoint.maStyleName )
                    aPoint.mnRepeat += aLastPoint.mnRepeat;
                else if( aLastPoint.mnRepeat > 0 )
                {
                    // write last element
                    if( aLastPoint.maStyleName.getLength() )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );

                    if( aLastPoint.mnRepeat > 1 )
                        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
                                            OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));

                    SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
                }
                aLastPoint = aPoint;
            }
            // write last element if it hasn't been written in last iteration
            if( aPoint.maStyleName == aLastPoint.maStyleName )
            {
                if( aLastPoint.maStyleName.getLength() )
                    mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );

                if( aLastPoint.mnRepeat > 1 )
                    mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
                                        OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));

                SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
            }
        }
    }
}


void SchXMLExportHelper_Impl::getCellAddress( sal_Int32 nCol, sal_Int32 nRow )
{
	msStringBuffer.append( (sal_Unicode)'.' );
	if( nCol < 26 )
		msStringBuffer.append( (sal_Unicode)('A' + nCol) );
	else if( nCol < 702 )
	{
		msStringBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 ));
		msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) );
	}
	else
	{
		msStringBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 ));
		msStringBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 ));
		msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) );
	}

	msStringBuffer.append( nRow + (sal_Int32)1 );
}

void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
{
    mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.X );
    msString = msStringBuffer.makeStringAndClear();
    mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );

    mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.Y );
    msString = msStringBuffer.makeStringAndClear();
    mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
}

void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
{
	if( xShape.is())
        addPosition( xShape->getPosition());
}

void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
{
    mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Width );
    msString = msStringBuffer.makeStringAndClear();
    mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH,  msString );


    mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Height);
    msString = msStringBuffer.makeStringAndClear();
    mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
}

void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
{
	if( xShape.is())
        addSize( xShape->getSize(), bIsOOoNamespace );
}

awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ) const
{
    awt::Size aSize( 8000, 7000 );
    uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
    DBG_ASSERT( xVisualObject.is(),"need XVisualObject for page size" );
    if( xVisualObject.is() )
        aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );

    return aSize;
}

void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
{
    if( !aStates.empty() )
        maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
}

void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
{
    if( !aStates.empty() )
    {
        DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );

        mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME,  maAutoStyleNameQueue.front() );
        maAutoStyleNameQueue.pop();
    }
}

void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs )
{
    SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs );
}

// ========================================
// class SchXMLExport
// ========================================

// #110680#
SchXMLExport::SchXMLExport(
	const Reference< lang::XMultiServiceFactory >& xServiceFactory,
	sal_uInt16 nExportFlags )
:	SvXMLExport( xServiceFactory, MAP_CM, ::xmloff::token::XML_CHART, nExportFlags ),
	maAutoStylePool( *this ),
	maExportHelper( *this, maAutoStylePool )
{
    if( getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST )
        _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
}


SchXMLExport::~SchXMLExport()
{
	// stop progress view
	if( mxStatusIndicator.is())
	{
		mxStatusIndicator->end();
		mxStatusIndicator->reset();
	}
}

sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
{
    Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
    maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc );
    return SvXMLExport::exportDoc( eClass );
}

void SchXMLExport::_ExportStyles( sal_Bool bUsed )
{
	SvXMLExport::_ExportStyles( bUsed );
}

void SchXMLExport::_ExportMasterStyles()
{
	// not available in chart
	DBG_WARNING( "Master Style Export requested. Not available for Chart" );
}

void SchXMLExport::_ExportAutoStyles()
{
	// there are no styles that require their own autostyles
	if( getExportFlags() & EXPORT_CONTENT )
	{
		Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
		if( xChartDoc.is())
		{
			maExportHelper.m_pImpl->collectAutoStyles( xChartDoc );
			maExportHelper.m_pImpl->exportAutoStyles();
		}
		else
		{
			DBG_ERROR( "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
		}
	}
}

void SchXMLExport::_ExportContent()
{
	Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
	if( xChartDoc.is())
	{
		// determine if data comes from the outside
		sal_Bool bIncludeTable = sal_True;

        Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
        if( xNewDoc.is())
        {
            // check if we have own data.  If so we must not export the complete
            // range string, as this is our only indicator for having own or
            // external data. @todo: fix this in the file format!
            Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
            if( ! (xDPServiceInfo.is() &&
                   xDPServiceInfo->getImplementationName().equalsAsciiL(
                       RTL_CONSTASCII_STRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" ))))
            {
                bIncludeTable = sal_False;
            }
        }
        else
        {
            Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
            if( xServ.is())
            {
                if( xServ->supportsService(
                        OUString::createFromAscii( "com.sun.star.chart.ChartTableAddressSupplier" )))
                {
                    Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
                    if( xProp.is())
                    {
                        Any aAny;
                        try
                        {
                            OUString sChartAddress;
                            aAny = xProp->getPropertyValue(
                                OUString::createFromAscii( "ChartRangeAddress" ));
                            aAny >>= sChartAddress;
                            maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress );

                            OUString sTableNumberList;
                            aAny = xProp->getPropertyValue(
                                OUString::createFromAscii( "TableNumberList" ));
                            aAny >>= sTableNumberList;
                            maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList );

                            // do not include own table if there are external addresses
                            bIncludeTable = (sChartAddress.getLength() == 0);
                        }
                        catch( beans::UnknownPropertyException & )
                        {
                            DBG_ERROR( "Property ChartRangeAddress not supported by ChartDocument" );
                        }
                    }
                }
            }
        }
        maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable );
	}
	else
	{
		DBG_ERROR( "Couldn't export chart due to wrong XModel" );
	}
}

void SchXMLExport::SetProgress( sal_Int32 nPercentage )
{
	// set progress view
	if( mxStatusIndicator.is())
		mxStatusIndicator->setValue( nPercentage );
}

UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
{
    return maExportHelper.m_pImpl->GetPropertySetMapper();
}

void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
{
    if( xChartDoc.is())
        try
        {
            Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
            OSL_ENSURE( xDataProvider.is(), "No DataProvider" );
            if( xDataProvider.is())
            {
                Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
                Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
                ::rtl::OUString sCellRange, sBrokenRange;
                bool bBrokenRangeAvailable = false;
                for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
                {
                    if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
                        aArgs[i].Value >>= sCellRange;
                    else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("BrokenCellRangeForExport")))
                    {
                        if( aArgs[i].Value >>= sBrokenRange )
                            bBrokenRangeAvailable = true;
                    }
                    else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DataRowSource")))
                    {
                        chart::ChartDataRowSource eRowSource;
                        aArgs[i].Value >>= eRowSource;
                        mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
                    }
                    else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FirstCellAsLabel")))
                        aArgs[i].Value >>= mbHasSeriesLabels;
                    else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
                        aArgs[i].Value >>= maSequenceMapping;
                    else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("TableNumberList")))
                        aArgs[i].Value >>= msTableNumberList;
                }

                // #i79009# For Writer we have to export a broken version of the
                // range, where every row number is noe too large, so that older
                // version can correctly read those files.
                msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
                if( msChartAddress.getLength() > 0 )
                {
                    // convert format to XML-conform one
                    Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
                    if( xConversion.is())
                        msChartAddress = xConversion->convertRangeToXML( msChartAddress );
                }
            }
        }
        catch( uno::Exception & ex )
        {
            (void)ex; // avoid warning for pro build
            OSL_ENSURE( false, OUStringToOString(
                            OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
                            OUString::createFromAscii( typeid( ex ).name()) +
                            OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
                            ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
        }
}

// export components ========================================

// first version: everything goes in one storage

Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLExporter" ) );
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Compact" ) );
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
{
	// #110680#
    // #103997# removed some flags from EXPORT_ALL
	// return (cppu::OWeakObject*)new SchXMLExport( EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
}

// Oasis format
Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisExporter" ) );
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Compact" ) );
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
{
    // #103997# removed some flags from EXPORT_ALL
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr,
        (EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )) | EXPORT_OASIS );
}

// ============================================================

// multiple storage version: one for content / styles / meta

Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLStylesExporter" ));
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Styles" ));
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr) throw( uno::Exception )
{
	// #110680#
	// return (cppu::OWeakObject*)new SchXMLExport( EXPORT_STYLES );
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES );
}

// Oasis format
Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisStylesExporter" ));
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Styles" ));
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
{
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES | EXPORT_OASIS );
}

// ------------------------------------------------------------

Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLContentExporter" ));
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Content" ));
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
{
	// #110680#
	// return (cppu::OWeakObject*)new SchXMLExport( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
}

// Oasis format
Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisContentExporter" ));
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Content" ));
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
{
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS );
}

// ------------------------------------------------------------

// Sequence< OUString > SAL_CALL SchXMLExport_Meta_getSupportedServiceNames() throw()
// {
// 	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLMetaExporter" ));
// 	const Sequence< OUString > aSeq( &aServiceName, 1 );
// 	return aSeq;
// }

// OUString SAL_CALL SchXMLExport_Meta_getImplementationName() throw()
// {
// 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Meta" ));
// }

// Reference< uno::XInterface > SAL_CALL SchXMLExport_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
// {
// 	return (cppu::OWeakObject*)new SchXMLExport( EXPORT_META );
// }

// Oasis format
Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
{
	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisMetaExporter" ));
	const Sequence< OUString > aSeq( &aServiceName, 1 );
	return aSeq;
}

OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Meta" ));
}

Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
{
	return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_META | EXPORT_OASIS  );
}


// XServiceInfo
OUString SAL_CALL SchXMLExport::getImplementationName() throw( uno::RuntimeException )
{
    switch( getExportFlags())
    {
        case EXPORT_ALL:
            return SchXMLExport_getImplementationName();
        case EXPORT_STYLES:
            return SchXMLExport_Styles_getImplementationName();
        case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ):
            return SchXMLExport_Content_getImplementationName();
//         case EXPORT_META:
//             return SchXMLExport_Meta_getImplementationName();

        // Oasis format
        case ( EXPORT_ALL | EXPORT_OASIS ):
            return SchXMLExport_Oasis_getImplementationName();
        case ( EXPORT_STYLES | EXPORT_OASIS ):
            return SchXMLExport_Oasis_Styles_getImplementationName();
        case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS  ):
            return SchXMLExport_Oasis_Content_getImplementationName();
        case ( EXPORT_META | EXPORT_OASIS ):
            return SchXMLExport_Oasis_Meta_getImplementationName();

        case EXPORT_SETTINGS:
        // there is no settings component in chart
        default:
            return OUString::createFromAscii( "SchXMLExport" );
    }
}
