/**************************************************************
 *
 * 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_chart2.hxx"
#include <rtl/math.hxx>

#include <valarray>

#include "InternalDataProvider.hxx"
#include "LabeledDataSequence.hxx"
#include "DataSource.hxx"
#include "PropertyHelper.hxx"
#include "macros.hxx"
#include "XMLRangeHelper.hxx"
#include "ContainerHelper.hxx"
#include "CommonConverters.hxx"
#include "CommonFunctors.hxx"
#include "UncachedDataSequence.hxx"
#include "DataSourceHelper.hxx"
#include "ChartModelHelper.hxx"
#include "DiagramHelper.hxx"
#include "ExplicitCategoriesProvider.hxx"

#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/data/XDataSequence.hpp>
#include <com/sun/star/chart/ChartDataRowSource.hpp>
#include <rtl/ustrbuf.hxx>
#include <unotools/charclass.hxx>
#include <comphelper/sequenceashashmap.hxx>

#include <vector>
#include <algorithm>

using namespace ::com::sun::star;
using namespace ::std;

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;

namespace chart
{

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

namespace
{

// note: in xmloff this name is used to indicate usage of own data
static const ::rtl::OUString lcl_aServiceName(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" ));

static const ::rtl::OUString lcl_aCategoriesRangeName(
    RTL_CONSTASCII_USTRINGPARAM( "categories" ));
static const ::rtl::OUString lcl_aCategoriesLevelRangeNamePrefix(
    RTL_CONSTASCII_USTRINGPARAM( "categoriesL " )); //L <-> level
static const ::rtl::OUString lcl_aCategoriesPointRangeNamePrefix(
    RTL_CONSTASCII_USTRINGPARAM( "categoriesP " )); //P <-> point
static const ::rtl::OUString lcl_aCategoriesRoleName(
    RTL_CONSTASCII_USTRINGPARAM( "categories" ));
static const ::rtl::OUString lcl_aLabelRangePrefix(
    RTL_CONSTASCII_USTRINGPARAM( "label " ));
static const ::rtl::OUString lcl_aCompleteRange(
    RTL_CONSTASCII_USTRINGPARAM( "all" ));

typedef ::std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > >
    lcl_tSequenceMap;

Sequence< OUString > lcl_AnyToStringSequence( const Sequence< uno::Any >& aAnySeq )
{
    Sequence< OUString > aResult;
    aResult.realloc( aAnySeq.getLength() );
    transform( aAnySeq.getConstArray(), aAnySeq.getConstArray() + aAnySeq.getLength(),
               aResult.getArray(), CommonFunctors::AnyToString() );
    return aResult;
}

Sequence< uno::Any > lcl_StringToAnySequence( const Sequence< OUString >& aStringSeq )
{
    Sequence< uno::Any > aResult;
    aResult.realloc( aStringSeq.getLength() );
    transform( aStringSeq.getConstArray(), aStringSeq.getConstArray() + aStringSeq.getLength(),
               aResult.getArray(), CommonFunctors::makeAny< OUString >() );
    return aResult;
}

struct lcl_setModified : public ::std::unary_function< lcl_tSequenceMap, void >
{
    void operator() ( const lcl_tSequenceMap::value_type & rMapEntry )
    {
        // convert weak reference to reference
        Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second );
        if( xSeq.is())
        {
            Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY );
            if( xMod.is())
                xMod->setModified( sal_True );
        }
    }
};

struct lcl_internalizeSeries : public ::std::unary_function< Reference< chart2::XDataSeries >, void >
{
    lcl_internalizeSeries( InternalData & rInternalData,
                           InternalDataProvider & rProvider,
                           bool bConnectToModel, bool bDataInColumns ) :
            m_rInternalData( rInternalData ),
            m_rProvider( rProvider ),
            m_bConnectToModel( bConnectToModel ),
            m_bDataInColumns( bDataInColumns )
    {}
    void operator() ( const Reference< chart2::XDataSeries > & xSeries )
    {
        Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
        Reference< chart2::data::XDataSink >   xSink(   xSeries, uno::UNO_QUERY );
        if( xSource.is() && xSink.is() )
        {
            Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeriesData = xSource->getDataSequences();
            Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.getLength() );
            for( sal_Int32 i=0; i<aOldSeriesData.getLength(); ++i )
            {
                sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() );
                OUString aIdentifier( OUString::valueOf( nNewIndex ));
                //@todo: deal also with genericXDataSequence
                Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY );
                Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY );
                Reference< chart2::data::XDataSequence > xNewValues;

                if( xValues.is() )
                {
                    ::std::vector< double > aValues( ContainerHelper::SequenceToVector( xValues->getNumericalData()));
                    if( m_bDataInColumns )
                        m_rInternalData.setColumnValues( nNewIndex, aValues );
                    else
                        m_rInternalData.setRowValues( nNewIndex, aValues );
                    if( m_bConnectToModel )
                    {
                        xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier ));
                        comphelper::copyProperties(
                            Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ),
                            Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY ));
                    }
                }

                if( xLabel.is() )
                {
                    if( m_bDataInColumns )
                        m_rInternalData.setComplexColumnLabel( nNewIndex, ContainerHelper::SequenceToVector( lcl_StringToAnySequence( xLabel->getTextualData() ) ) );
                    else
                        m_rInternalData.setComplexRowLabel( nNewIndex, ContainerHelper::SequenceToVector( lcl_StringToAnySequence( xLabel->getTextualData() ) ) );
                    if( m_bConnectToModel )
                    {
                        Reference< chart2::data::XDataSequence > xNewLabel(
                            m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier ));
                        comphelper::copyProperties(
                            Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ),
                            Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY ));
                        aNewSeriesData[i] = Reference< chart2::data::XLabeledDataSequence >(
                                new LabeledDataSequence( xNewValues, xNewLabel ));
                    }
                }
                else
                {
                    if( m_bConnectToModel )
                        aNewSeriesData[i] = Reference< chart2::data::XLabeledDataSequence >(
                            new LabeledDataSequence( xNewValues ));
                }
            }
            if( m_bConnectToModel )
                xSink->setData( aNewSeriesData );
        }
     }

private:
    InternalData &          m_rInternalData;
    InternalDataProvider &  m_rProvider;
    bool                    m_bConnectToModel;
    bool                    m_bDataInColumns;
};

struct lcl_copyFromLevel : public ::std::unary_function< vector< uno::Any >, uno::Any >
{
public:

    explicit lcl_copyFromLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
    {}

    uno::Any operator() ( const vector< uno::Any >& rVector )
    {
        uno::Any aRet;
        if( m_nLevel <  static_cast< sal_Int32 >(rVector.size()) )
            aRet = rVector[m_nLevel];
        return aRet;
    }

private:
    sal_Int32 m_nLevel;
};

struct lcl_getStringFromLevelVector : public ::std::unary_function< vector< uno::Any >, OUString >
{
public:

    explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
    {}

    OUString operator() ( const vector< uno::Any >& rVector )
    {
        OUString aString;
        if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
            aString = CommonFunctors::AnyToString()(rVector[m_nLevel]);
        return aString;
    }

private:
    sal_Int32 m_nLevel;
};


struct lcl_setAnyAtLevel : public ::std::binary_function< vector< uno::Any >, uno::Any, vector< uno::Any > >
{
public:

    explicit lcl_setAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
    {}

    vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const uno::Any& rNewValue )
    {
        vector< uno::Any > aRet( rVector );
        if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
            aRet.resize( m_nLevel+1 );
        aRet[ m_nLevel ]=rNewValue;
        return aRet;
    }

private:
    sal_Int32 m_nLevel;
};

struct lcl_setAnyAtLevelFromStringSequence : public ::std::binary_function< vector< uno::Any >, OUString, vector< uno::Any > >
{
public:

    explicit lcl_setAnyAtLevelFromStringSequence( sal_Int32 nLevel ) : m_nLevel( nLevel )
    {}

    vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const OUString& rNewValue )
    {
        vector< uno::Any > aRet( rVector );
        if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
            aRet.resize( m_nLevel+1 );
        aRet[ m_nLevel ]=uno::makeAny(rNewValue);
        return aRet;
    }

private:
    sal_Int32 m_nLevel;
};

struct lcl_insertAnyAtLevel : public ::std::unary_function< vector< uno::Any >, void >
{
public:

    explicit lcl_insertAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
    {}

    void operator() ( vector< uno::Any >& rVector )
    {
        if( m_nLevel > static_cast< sal_Int32 >(rVector.size()) )
            rVector.resize( m_nLevel );

        vector< uno::Any >::iterator aIt( rVector.begin() );
        for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++)
        {
            if( nN==m_nLevel )
                break;
        }
        rVector.insert( aIt, uno::Any() );
    }

private:
    sal_Int32 m_nLevel;
};

struct lcl_removeAnyAtLevel : public ::std::unary_function< vector< uno::Any >, void >
{
public:

    explicit lcl_removeAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
    {}

    void operator() ( vector< uno::Any >& rVector )
    {
        vector< uno::Any >::iterator aIt( rVector.begin() );
        for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++)
        {
            if( nN==m_nLevel )
            {
                rVector.erase( aIt );
                break;
            }
        }
    }

private:
    sal_Int32 m_nLevel;
};

} // anonymous namespace

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

InternalDataProvider::InternalDataProvider( const Reference< uno::XComponentContext > & /*_xContext*/)
    : m_bDataInColumns( true )
{}

InternalDataProvider::InternalDataProvider(
    const Reference< chart2::XChartDocument > & xChartDoc,
    bool bConnectToModel,
    bool bDefaultDataInColumns)
:   m_bDataInColumns( bDefaultDataInColumns )
{
    try
    {
        Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) );
        if( xDiagram.is())
        {
            Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );

            //data in columns?
            {
                ::rtl::OUString aRangeString;
                bool bFirstCellAsLabel = true;
                bool bHasCategories = true;
                uno::Sequence< sal_Int32 > aSequenceMapping;
                const bool bSomethingDetected(
                    DataSourceHelper::detectRangeSegmentation(
                        xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ));

                // #120559# if no data was available, restore default
                if(!bSomethingDetected && m_bDataInColumns != bDefaultDataInColumns)
                {
                    m_bDataInColumns = bDefaultDataInColumns;
                }
            }

            // categories
            {
                vector< vector< uno::Any > > aNewCategories;//inner count is level
                {
                    ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), xChartModel );

                    const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() );
                    sal_Int32 nLevelCount = rSplitCategoriesList.getLength();
                    for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
                    {
                        Reference< chart2::data::XLabeledDataSequence > xLDS( rSplitCategoriesList[nL] );
                        if( !xLDS.is() )
                            continue;
                        Sequence< uno::Any > aDataSeq;
                        Reference< chart2::data::XDataSequence > xSeq( xLDS->getValues() );
                        if( xSeq.is() )
                            aDataSeq = xSeq->getData();
                        sal_Int32 nLength = aDataSeq.getLength();
                        sal_Int32 nCatLength = static_cast< sal_Int32 >(aNewCategories.size());
                        if( nCatLength < nLength )
                            aNewCategories.resize( nLength );
                        else if( nLength < nCatLength )
                            aDataSeq.realloc( nCatLength );
                        transform( aNewCategories.begin(), aNewCategories.end(), aDataSeq.getConstArray(),
                            aNewCategories.begin(), lcl_setAnyAtLevel(nL) );
                    }
                    if( !nLevelCount )
                    {
                        Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories();
                        sal_Int32 nLength = aSimplecategories.getLength();
                        aNewCategories.reserve( nLength );
                        for( sal_Int32 nN=0; nN<nLength; nN++)
                        {
                            vector< uno::Any > aVector(1);
                            aVector[0] = uno::makeAny( aSimplecategories[nN] );
                            aNewCategories.push_back( aVector );
                        }
                    }
                }

                if( m_bDataInColumns )
                    m_aInternalData.setComplexRowLabels( aNewCategories );
                else
                    m_aInternalData.setComplexColumnLabels( aNewCategories );
                if( bConnectToModel )
                    DiagramHelper::setCategoriesToDiagram( new LabeledDataSequence(
                        createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), xDiagram );
            }

            // data series
            ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc ));
            ::std::for_each( aSeriesVector.begin(), aSeriesVector.end(), lcl_internalizeSeries( m_aInternalData, *this, bConnectToModel, m_bDataInColumns ) );
        }
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

// copy-CTOR
InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) :
        impl::InternalDataProvider_Base(),
        m_aSequenceMap( rOther.m_aSequenceMap ),
        m_aInternalData( rOther.m_aInternalData ),
        m_bDataInColumns( rOther.m_bDataInColumns )
{}

InternalDataProvider::~InternalDataProvider()
{}

void InternalDataProvider::lcl_addDataSequenceToMap(
    const OUString & rRangeRepresentation,
    const Reference< chart2::data::XDataSequence > & xSequence )
{
    m_aSequenceMap.insert(
        tSequenceMap::value_type(
            rRangeRepresentation,
            uno::WeakReference< chart2::data::XDataSequence >( xSequence )));
}

void InternalDataProvider::lcl_deleteMapReferences( const OUString & rRangeRepresentation )
{
    // set sequence to deleted by setting its range to an empty string
    tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation ));
    for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
    {
        Reference< chart2::data::XDataSequence > xSeq( aIt->second );
        if( xSeq.is())
        {
            Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
            if( xNamed.is())
                xNamed->setName( OUString());
        }
    }
    // remove from map
    m_aSequenceMap.erase( aRange.first, aRange.second );
}

void InternalDataProvider::lcl_adaptMapReferences(
    const OUString & rOldRangeRepresentation,
    const OUString & rNewRangeRepresentation )
{
    tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation ));
    tSequenceMap aNewElements;
    for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
    {
        Reference< chart2::data::XDataSequence > xSeq( aIt->second );
        if( xSeq.is())
        {
            Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
            if( xNamed.is())
                xNamed->setName( rNewRangeRepresentation );
        }
        aNewElements.insert( tSequenceMap::value_type( rNewRangeRepresentation, aIt->second ));
    }
    // erase map values for old index
    m_aSequenceMap.erase( aRange.first, aRange.second );
    // add new entries for values with new index
    ::std::copy( aNewElements.begin(), aNewElements.end(),
                 ::std::inserter( m_aSequenceMap,
                                  m_aSequenceMap.upper_bound( rNewRangeRepresentation )));
}

void InternalDataProvider::lcl_increaseMapReferences(
    sal_Int32 nBegin, sal_Int32 nEnd )
{
    for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex )
    {
        lcl_adaptMapReferences( OUString::valueOf( nIndex ),
                            OUString::valueOf( nIndex + 1 ));
        lcl_adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ),
                            lcl_aLabelRangePrefix + OUString::valueOf( nIndex + 1 ));
    }
}

void InternalDataProvider::lcl_decreaseMapReferences(
    sal_Int32 nBegin, sal_Int32 nEnd )
{
    for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex )
    {
        lcl_adaptMapReferences( OUString::valueOf( nIndex ),
                            OUString::valueOf( nIndex - 1 ));
        lcl_adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ),
                            lcl_aLabelRangePrefix + OUString::valueOf( nIndex - 1 ));
    }
}

Reference< chart2::data::XDataSequence > InternalDataProvider::lcl_createDataSequenceAndAddToMap(
    const OUString & rRangeRepresentation )
{
    Reference< chart2::data::XDataSequence > xSeq(
        new UncachedDataSequence( this, rRangeRepresentation ));
    lcl_addDataSequenceToMap( rRangeRepresentation, xSeq );
    return xSeq;
}

Reference< chart2::data::XDataSequence > InternalDataProvider::lcl_createDataSequenceAndAddToMap(
    const OUString & rRangeRepresentation,
    const OUString & rRole )
{
    Reference< chart2::data::XDataSequence > xSeq(
        new UncachedDataSequence( this, rRangeRepresentation, rRole ));
    lcl_addDataSequenceToMap( rRangeRepresentation, xSeq );
    return xSeq;
}

void InternalDataProvider::createDefaultData()
{
    m_aInternalData.createDefaultData();
}

// ____ XDataProvider ____
::sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ )
    throw (uno::RuntimeException)
{
    return true;
}

namespace
{

sal_Int32 lcl_getInnerLevelCount( const vector< vector< uno::Any > >& rLabels )
{
    sal_Int32 nCount = 1;//minimum is 1!
    vector< vector< uno::Any > >::const_iterator aLevelIt( rLabels.begin() );
    vector< vector< uno::Any > >::const_iterator aLevelEnd( rLabels.end() );
    for( ;aLevelIt!=aLevelEnd; ++aLevelIt )
    {
        const vector< uno::Any >& rCurrentLevelLabels = *aLevelIt;
        nCount = std::max<sal_Int32>( rCurrentLevelLabels.size(), nCount );
    }
    return nCount;
}

}//end anonymous namespace

Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource(
    const Sequence< beans::PropertyValue >& aArguments )
    throw (lang::IllegalArgumentException,
           uno::RuntimeException)
{
    OUString aRangeRepresentation;
    bool bUseColumns = true;
    bool bFirstCellAsLabel = true;
    bool bHasCategories = true;
    uno::Sequence< sal_Int32 > aSequenceMapping;
    DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );

    if( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) )
    {
        //return split complex categories if we have any:
        ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories;
        vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
        if( bUseColumns==m_bDataInColumns )
        {
            sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
            for( sal_Int32 nL=0; nL<nLevelCount; nL++ )
                aComplexCategories.push_back( new LabeledDataSequence(
                    new UncachedDataSequence( this
                        , lcl_aCategoriesLevelRangeNamePrefix + OUString::valueOf( nL )
                        , lcl_aCategoriesRoleName ) ) );
        }
        else
        {
            sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount();
            for( sal_Int32 nP=0; nP<nPointCount; nP++ )
                aComplexCategories.push_back( new LabeledDataSequence(
                    new UncachedDataSequence( this
                        , lcl_aCategoriesPointRangeNamePrefix + OUString::valueOf( nP )
                        , lcl_aCategoriesRoleName ) ) );
        }
        //don't add the created sequences to the map as they are used temporarily only ...
        return new DataSource( ContainerHelper::ContainerToSequence(aComplexCategories) );
    }

    OSL_ASSERT( aRangeRepresentation.equals( lcl_aCompleteRange ));

    ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec;

    // categories
    if( bHasCategories )
        aResultLSeqVec.push_back(
            new LabeledDataSequence( lcl_createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) );

    // data with labels
    ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec;
    const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount());
    for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
    {
        aDataVec.push_back(
            new LabeledDataSequence(
                lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIdx )),
                lcl_createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIdx ))));
    }

    // attention: this data provider has the limitation that it stores
    // internally if data comes from columns or rows. It is intended for
    // creating only one used data source.
    // @todo: add this information in the range representation strings
    m_bDataInColumns = bUseColumns;

    //reorder labeled sequences according to aSequenceMapping; ignore categories
    for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
    {
        std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex];
        if( nOldIndex < aDataVec.size() )
        {
            if( aDataVec[nOldIndex].is() )
            {
                aResultLSeqVec.push_back( aDataVec[nOldIndex] );
                aDataVec[nOldIndex] = 0;
            }
        }
    }

    //add left over data sequences to result
    ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aIt(aDataVec.begin());
    const ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aEndIt(aDataVec.end());
    for( ;aIt!=aEndIt; ++aIt)
    {
        if( aIt->is() )
            aResultLSeqVec.push_back( *aIt );
    }

    return new DataSource( ContainerHelper::ContainerToSequence(aResultLSeqVec) );
}

Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments(
    const Reference< chart2::data::XDataSource >& /* xDataSource */ )
    throw (uno::RuntimeException)
{
    Sequence< beans::PropertyValue > aArguments( 4 );
    aArguments[0] = beans::PropertyValue(
        C2U("CellRangeRepresentation"), -1, uno::makeAny( lcl_aCompleteRange ),
        beans::PropertyState_DIRECT_VALUE );
    aArguments[1] = beans::PropertyValue(
        C2U("DataRowSource"), -1, uno::makeAny(
            m_bDataInColumns
            ? ::com::sun::star::chart::ChartDataRowSource_COLUMNS
            : ::com::sun::star::chart::ChartDataRowSource_ROWS ),
        beans::PropertyState_DIRECT_VALUE );
    // internal data always contains labels and categories
    aArguments[2] = beans::PropertyValue(
        C2U("FirstCellAsLabel"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE );
    aArguments[3] = beans::PropertyValue(
        C2U("HasCategories"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE );

    // #i85913# Sequence Mapping is not needed for internal data, as it is
    // applied to the data when the data source is created.

    return aArguments;
}

::sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
    throw (uno::RuntimeException)
{
    return true;
}

Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation(
    const OUString& aRangeRepresentation )
    throw (lang::IllegalArgumentException,
           uno::RuntimeException)
{
    if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
    {
        OSL_ASSERT( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implemented that only parts of the categories are really requested

        // categories
        return lcl_createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
    }
    else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
    {
        // label
        sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
        return lcl_createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ));
    }
    else if( aRangeRepresentation.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "last" )))
    {
        sal_Int32 nIndex = (m_bDataInColumns
                            ? m_aInternalData.getColumnCount()
                            : m_aInternalData.getRowCount()) - 1;
        return lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIndex ));
    }
    else if( !aRangeRepresentation.isEmpty() )
    {
        // data
        sal_Int32 nIndex = aRangeRepresentation.toInt32();
        return lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIndex ));
    }

    return Reference< chart2::data::XDataSequence >();
}

Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection()
    throw (uno::RuntimeException)
{
    // there is no range selection component
    return Reference< sheet::XRangeSelection >();
}

// ____ XInternalDataProvider ____
::sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange )
    throw (uno::RuntimeException)
{
    sal_Bool bResult = false;

    if( aRange.match( lcl_aCategoriesRangeName ))
    {
        OSL_ASSERT( aRange.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implemented that only parts of the categories are really requested
        bResult = true;
    }
    else if( aRange.match( lcl_aLabelRangePrefix ))
    {
        sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
        bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
    }
    else
    {
        sal_Int32 nIndex = aRange.toInt32();
        bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
    }

    return bResult;
}

Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange )
    throw (uno::RuntimeException)
{
    Sequence< uno::Any > aResult;

    if( aRange.match( lcl_aLabelRangePrefix ) )
    {
        sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
        vector< uno::Any > aComplexLabel = m_bDataInColumns
            ? m_aInternalData.getComplexColumnLabel( nIndex )
            : m_aInternalData.getComplexRowLabel( nIndex );
        if( !aComplexLabel.empty() )
            aResult = ContainerHelper::ContainerToSequence(aComplexLabel);
    }
    else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
    {
        sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesPointRangeNamePrefix.getLength() ).toInt32();
        vector< uno::Any > aComplexCategory = m_bDataInColumns
            ? m_aInternalData.getComplexRowLabel( nPointIndex )
            : m_aInternalData.getComplexColumnLabel( nPointIndex );
        if( !aComplexCategory.empty() )
            aResult = ContainerHelper::ContainerToSequence(aComplexCategory);
    }
    else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
    {
        sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength() ).toInt32();
        vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
        if( nLevel < lcl_getInnerLevelCount( aCategories ) )
        {
            aResult.realloc( aCategories.size() );
            transform( aCategories.begin(), aCategories.end(),
                       aResult.getArray(), lcl_copyFromLevel(nLevel) );
        }
    }
    else if( aRange.equals( lcl_aCategoriesRangeName ) )
    {
        vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
        sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
        if( nLevelCount == 1 )
        {
            sal_Int32 nL=0;
            aResult = this->getDataByRangeRepresentation( lcl_aCategoriesLevelRangeNamePrefix + OUString::valueOf( nL ) );
        }
        else
        {
            Sequence< OUString > aLabels = m_bDataInColumns ? this->getRowDescriptions() : this->getColumnDescriptions();
            aResult.realloc( aLabels.getLength() );
            transform( aLabels.getConstArray(), aLabels.getConstArray() + aLabels.getLength(),
                       aResult.getArray(), CommonFunctors::makeAny< OUString >() );
        }
    }
    else
    {
        sal_Int32 nIndex = aRange.toInt32();
        if( nIndex >= 0 )
        {
            Sequence< double > aData;
            if( m_bDataInColumns )
                aData = m_aInternalData.getColumnValues(nIndex);
            else
                aData = m_aInternalData.getRowValues(nIndex);
            if( aData.getLength() )
            {
			    aResult.realloc( aData.getLength());
                transform( aData.getConstArray(), aData.getConstArray() + aData.getLength(),
                           aResult.getArray(), CommonFunctors::makeAny< double >());
            }
        }
    }

    return aResult;
}

void SAL_CALL InternalDataProvider::setDataByRangeRepresentation(
    const OUString& aRange, const Sequence< uno::Any >& aNewData )
    throw (uno::RuntimeException)
{
    vector< uno::Any > aNewVector( ContainerHelper::SequenceToVector(aNewData) );
    if( aRange.match( lcl_aLabelRangePrefix ) )
    {
        sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
        if( m_bDataInColumns )
            m_aInternalData.setComplexColumnLabel( nIndex, aNewVector );
        else
            m_aInternalData.setComplexRowLabel( nIndex, aNewVector );
    }
    else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
    {
        sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32();
        if( m_bDataInColumns )
            m_aInternalData.setComplexRowLabel( nPointIndex, aNewVector );
        else
            m_aInternalData.setComplexColumnLabel( nPointIndex, aNewVector );
    }
    else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
    {
        sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32();
        vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();

        //ensure equal length
        if( aNewVector.size() > aComplexCategories.size() )
            aComplexCategories.resize( aNewVector.size() );
        else if( aNewVector.size() < aComplexCategories.size() )
            aNewVector.resize( aComplexCategories.size() );

        transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
                   aComplexCategories.begin(), lcl_setAnyAtLevel(nLevel) );

        if( m_bDataInColumns )
            m_aInternalData.setComplexRowLabels( aComplexCategories );
        else
            m_aInternalData.setComplexColumnLabels( aComplexCategories );
    }
    else if( aRange.equals( lcl_aCategoriesRangeName ) )
    {
        vector< vector< uno::Any > > aComplexCategories;
        aComplexCategories.resize( aNewVector.size() );
        transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
                            aComplexCategories.begin(), lcl_setAnyAtLevel(0) );
        if( m_bDataInColumns )
            m_aInternalData.setComplexRowLabels( aComplexCategories );
        else
            m_aInternalData.setComplexColumnLabels( aComplexCategories );
    }
    else
    {
        sal_Int32 nIndex = aRange.toInt32();
        if( nIndex>=0 )
        {
            vector< double > aNewDataVec;
            transform( aNewData.getConstArray(), aNewData.getConstArray() + aNewData.getLength(),
                       back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble());
            if( m_bDataInColumns )
                m_aInternalData.setColumnValues( nIndex, aNewDataVec );
            else
                m_aInternalData.setRowValues( nIndex, aNewDataVec );
        }
    }
}

void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex )
    throw (uno::RuntimeException)
{
    if( m_bDataInColumns )
    {
        lcl_increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount());
        m_aInternalData.insertColumn( nAfterIndex );
    }
    else
    {
        lcl_increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount());
        m_aInternalData.insertRow( nAfterIndex );
    }
}

void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex )
    throw (uno::RuntimeException)
{
    lcl_deleteMapReferences( OUString::valueOf( nAtIndex ));
    lcl_deleteMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nAtIndex ));
    if( m_bDataInColumns )
    {
        lcl_decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount());
        m_aInternalData.deleteColumn( nAtIndex );
    }
    else
    {
        lcl_decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount());
        m_aInternalData.deleteRow( nAtIndex );
    }
}

void SAL_CALL InternalDataProvider::appendSequence()
    throw (uno::RuntimeException)
{
    if( m_bDataInColumns )
        m_aInternalData.appendColumn();
    else
        m_aInternalData.appendRow();
}

void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel )
        throw (uno::RuntimeException)
{
    OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
    if( nLevel>0 )
    {
        vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
        ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertAnyAtLevel(nLevel) );
        if( m_bDataInColumns )
            m_aInternalData.setComplexRowLabels( aComplexCategories );
        else
            m_aInternalData.setComplexColumnLabels( aComplexCategories );

        tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
        ::std::for_each( aRange.first, aRange.second, lcl_setModified());
    }
}
void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel )
        throw (uno::RuntimeException)
{
    OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
    if( nLevel>0 )
    {
        vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
        ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeAnyAtLevel(nLevel) );
        if( m_bDataInColumns )
            m_aInternalData.setComplexRowLabels( aComplexCategories );
        else
            m_aInternalData.setComplexColumnLabels( aComplexCategories );

        tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
        ::std::for_each( aRange.first, aRange.second, lcl_setModified());
    }
}

void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex )
    throw (uno::RuntimeException)
{
    sal_Int32 nMaxRep = 0;
    if( m_bDataInColumns )
    {
        m_aInternalData.insertRow( nAfterIndex );
        nMaxRep = m_aInternalData.getColumnCount();
    }
    else
    {
        m_aInternalData.insertColumn( nAfterIndex );
        nMaxRep = m_aInternalData.getRowCount();
    }

    // notify change to all affected ranges
    tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0")));
    tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep )));
    ::std::for_each( aBegin, aEnd, lcl_setModified());

    tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
    ::std::for_each( aRange.first, aRange.second, lcl_setModified());
}

void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex )
    throw (uno::RuntimeException)
{
    sal_Int32 nMaxRep = 0;
    if( m_bDataInColumns )
    {
        m_aInternalData.deleteRow( nAtIndex );
        nMaxRep = m_aInternalData.getColumnCount();
    }
    else
    {
        m_aInternalData.deleteColumn( nAtIndex );
        nMaxRep = m_aInternalData.getRowCount();
    }

    // notify change to all affected ranges
    tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0")));
    tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep )));
    ::std::for_each( aBegin, aEnd, lcl_setModified());

    tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
    ::std::for_each( aRange.first, aRange.second, lcl_setModified());
}

void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex )
    throw (uno::RuntimeException)
{
    if( m_bDataInColumns )
        m_aInternalData.swapRowWithNext( nAtIndex );
    else
        m_aInternalData.swapColumnWithNext( nAtIndex );
    sal_Int32 nMaxRep = (m_bDataInColumns
                         ? m_aInternalData.getColumnCount()
                         : m_aInternalData.getRowCount());

    // notify change to all affected ranges
    tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0")));
    tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep )));
    ::std::for_each( aBegin, aEnd, lcl_setModified());

    tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
    ::std::for_each( aRange.first, aRange.second, lcl_setModified());
}

void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq )
    throw (uno::RuntimeException)
{
    if( xSeq.is())
        lcl_addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
}


// ____ XRangeXMLConversion ____
OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation )
    throw (lang::IllegalArgumentException,
           uno::RuntimeException)
{
    XMLRangeHelper::CellRange aRange;
    aRange.aTableName = OUString(RTL_CONSTASCII_USTRINGPARAM("local-table"));

    // attention: this data provider has the limitation that it stores
    // internally if data comes from columns or rows. It is intended for
    // creating only one used data source.
    // @todo: add this information in the range representation strings
    if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
    {
        OSL_ASSERT( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implemented that only parts of the categories are really requested
        aRange.aUpperLeft.bIsEmpty = false;
        if( m_bDataInColumns )
        {
            aRange.aUpperLeft.nColumn = 0;
            aRange.aUpperLeft.nRow = 1;
            aRange.aLowerRight = aRange.aUpperLeft;
            aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
        }
        else
        {
            aRange.aUpperLeft.nColumn = 1;
            aRange.aUpperLeft.nRow = 0;
            aRange.aLowerRight = aRange.aUpperLeft;
            aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
        }
    }
    else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
    {
        sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
        aRange.aUpperLeft.bIsEmpty = false;
        aRange.aLowerRight.bIsEmpty = true;
        if( m_bDataInColumns )
        {
            aRange.aUpperLeft.nColumn = nIndex + 1;
            aRange.aUpperLeft.nRow = 0;
        }
        else
        {
            aRange.aUpperLeft.nColumn = 0;
            aRange.aUpperLeft.nRow = nIndex + 1;
        }
    }
    else if( aRangeRepresentation.equals( lcl_aCompleteRange ))
    {
        aRange.aUpperLeft.bIsEmpty = false;
        aRange.aLowerRight.bIsEmpty = false;
        aRange.aUpperLeft.nColumn = 0;
        aRange.aUpperLeft.nRow = 0;
        aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
        aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
    }
    else
    {
        sal_Int32 nIndex = aRangeRepresentation.toInt32();
        aRange.aUpperLeft.bIsEmpty = false;
        if( m_bDataInColumns )
        {
            aRange.aUpperLeft.nColumn = nIndex + 1;
            aRange.aUpperLeft.nRow = 1;
            aRange.aLowerRight = aRange.aUpperLeft;
            aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
        }
        else
        {
            aRange.aUpperLeft.nColumn = 1;
            aRange.aUpperLeft.nRow = nIndex + 1;
            aRange.aLowerRight = aRange.aUpperLeft;
            aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
        }
    }

    return XMLRangeHelper::getXMLStringFromCellRange( aRange );
}

OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange )
    throw (lang::IllegalArgumentException,
           uno::RuntimeException)
{
    XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange ));
    if( aRange.aUpperLeft.bIsEmpty )
    {
        OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" );
        return OUString();
    }

    // "all"
    if( !aRange.aLowerRight.bIsEmpty &&
        ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) &&
        ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) )
        return lcl_aCompleteRange;

    // attention: this data provider has the limitation that it stores
    // internally if data comes from columns or rows. It is intended for
    // creating only one used data source.
    // @todo: add this information in the range representation strings

    // data in columns
    if( m_bDataInColumns )
    {
        if( aRange.aUpperLeft.nColumn == 0 )
            return lcl_aCategoriesRangeName;
        if( aRange.aUpperLeft.nRow == 0 )
            return lcl_aLabelRangePrefix + OUString::valueOf( aRange.aUpperLeft.nColumn - 1 );

        return OUString::valueOf( aRange.aUpperLeft.nColumn - 1 );
    }

    // data in rows
    if( aRange.aUpperLeft.nRow == 0 )
        return lcl_aCategoriesRangeName;
    if( aRange.aUpperLeft.nColumn == 0 )
        return lcl_aLabelRangePrefix + OUString::valueOf( aRange.aUpperLeft.nRow - 1 );

    return OUString::valueOf( aRange.aUpperLeft.nRow - 1 );
}

namespace
{

template< class Type >
Sequence< Sequence< Type > > lcl_convertVectorVectorToSequenceSequence( const vector< vector< Type > >& rIn )
{
    Sequence< Sequence< Type > > aRet;
    sal_Int32 nOuterCount = rIn.size();
    if( nOuterCount )
    {
        aRet.realloc(nOuterCount);
        for( sal_Int32 nN=0; nN<nOuterCount; nN++)
            aRet[nN]= ContainerHelper::ContainerToSequence( rIn[nN] );
    }
    return aRet;
}

template< class Type >
vector< vector< Type > > lcl_convertSequenceSequenceToVectorVector( const Sequence< Sequence< Type > >& rIn )
{
    vector< vector< Type > > aRet;
    sal_Int32 nOuterCount = rIn.getLength();
    if( nOuterCount )
    {
        aRet.resize(nOuterCount);
        for( sal_Int32 nN=0; nN<nOuterCount; nN++)
            aRet[nN]= ContainerHelper::SequenceToVector( rIn[nN] );
    }
    return aRet;
}

Sequence< Sequence< OUString > > lcl_convertComplexAnyVectorToStringSequence( const vector< vector< uno::Any > >& rIn )
{
    Sequence< Sequence< OUString > > aRet;
    sal_Int32 nOuterCount = rIn.size();
    if( nOuterCount )
    {
        aRet.realloc(nOuterCount);
        for( sal_Int32 nN=0; nN<nOuterCount; nN++)
            aRet[nN]= lcl_AnyToStringSequence( ContainerHelper::ContainerToSequence( rIn[nN] ) );
    }
    return aRet;
}

vector< vector< uno::Any > > lcl_convertComplexStringSequenceToAnyVector( const Sequence< Sequence< OUString > >& rIn )
{
    vector< vector< uno::Any > > aRet;
    sal_Int32 nOuterCount = rIn.getLength();
    for( sal_Int32 nN=0; nN<nOuterCount; nN++)
        aRet.push_back( ContainerHelper::SequenceToVector( lcl_StringToAnySequence( rIn[nN] ) ) );
    return aRet;
}

class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider
{
public:

    explicit SplitCategoriesProvider_ForComplexDescriptions( const ::std::vector< ::std::vector< uno::Any > >& rComplexDescriptions )
        : m_rComplexDescriptions( rComplexDescriptions )
    {}
    virtual ~SplitCategoriesProvider_ForComplexDescriptions()
    {}

    virtual sal_Int32 getLevelCount() const;
    virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const;

private:
    const ::std::vector< ::std::vector< uno::Any > >& m_rComplexDescriptions;
};

sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const
{
    return lcl_getInnerLevelCount( m_rComplexDescriptions );
}
uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const
{
    uno::Sequence< rtl::OUString > aResult;
    if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) )
    {
        aResult.realloc( m_rComplexDescriptions.size() );
        transform( m_rComplexDescriptions.begin(), m_rComplexDescriptions.end(),
                   aResult.getArray(), lcl_getStringFromLevelVector(nLevel) );
    }
    return aResult;
}

}//anonymous namespace

// ____ XDateCategories ____
Sequence< double > SAL_CALL InternalDataProvider::getDateCategories() throw (uno::RuntimeException)
{
    double fNan = InternalDataProvider::getNotANumber();
    double fValue = fNan;
    vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
    sal_Int32 nCount = aCategories.size();
    Sequence< double > aDoubles( nCount );
    vector< vector< uno::Any > >::iterator aIt( aCategories.begin() );
    vector< vector< uno::Any > >::const_iterator aEnd( aCategories.end() );
    for(sal_Int32 nN=0; nN<nCount && aIt!=aEnd; ++nN, ++aIt )
    {
        if( !( !aIt->empty() && ((*aIt)[0]>>=fValue) ) )
            fValue = fNan;
        aDoubles[nN]=fValue;
    }
    return aDoubles;
}

void SAL_CALL InternalDataProvider::setDateCategories( const Sequence< double >& rDates ) throw (uno::RuntimeException)
{
    sal_Int32 nCount = rDates.getLength();
    vector< vector< uno::Any > > aNewCategories;
    aNewCategories.reserve(nCount);
    vector< uno::Any > aSingleLabel(1);

    for(sal_Int32 nN=0; nN<nCount; ++nN )
    {
        aSingleLabel[0]=uno::makeAny(rDates[nN]);
        aNewCategories.push_back(aSingleLabel);
    }

    if( m_bDataInColumns )
        m_aInternalData.setComplexRowLabels( aNewCategories );
    else
        m_aInternalData.setComplexColumnLabels( aNewCategories );
}

// ____ XAnyDescriptionAccess ____
Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyRowDescriptions() throw (uno::RuntimeException)
{
    return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexRowLabels() );
}
void SAL_CALL InternalDataProvider::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& aRowDescriptions ) throw (uno::RuntimeException)
{
    m_aInternalData.setComplexRowLabels( lcl_convertSequenceSequenceToVectorVector( aRowDescriptions ) );
}
Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyColumnDescriptions() throw (uno::RuntimeException)
{
    return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexColumnLabels() );
}
void SAL_CALL InternalDataProvider::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& aColumnDescriptions ) throw (uno::RuntimeException)
{
    m_aInternalData.setComplexColumnLabels( lcl_convertSequenceSequenceToVectorVector( aColumnDescriptions ) );
}

// ____ XComplexDescriptionAccess ____
Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions() throw (uno::RuntimeException)
{
    return lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexRowLabels() );
}
void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aRowDescriptions ) throw (uno::RuntimeException)
{
    m_aInternalData.setComplexRowLabels( lcl_convertComplexStringSequenceToAnyVector(aRowDescriptions) );
}
Sequence< Sequence< ::rtl::OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions() throw (uno::RuntimeException)
{
    return lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexColumnLabels() );
}
void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aColumnDescriptions ) throw (uno::RuntimeException)
{
    m_aInternalData.setComplexColumnLabels( lcl_convertComplexStringSequenceToAnyVector(aColumnDescriptions) );
}

// ____ XChartDataArray ____
Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData()
    throw (uno::RuntimeException)
{
    return m_aInternalData.getData();
}

void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows )
    throw (uno::RuntimeException)
{
    return m_aInternalData.setData( rDataInRows );
}

void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions )
    throw (uno::RuntimeException)
{
    vector< vector< uno::Any > > aComplexDescriptions( aRowDescriptions.getLength() );
    transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(),
               aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
    m_aInternalData.setComplexRowLabels( aComplexDescriptions );
}

void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
    throw (uno::RuntimeException)
{
    vector< vector< uno::Any > > aComplexDescriptions( aColumnDescriptions.getLength() );
    transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(),
               aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
    m_aInternalData.setComplexColumnLabels( aComplexDescriptions );
}

Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
    throw (uno::RuntimeException)
{
    vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexRowLabels() );
    SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
    return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
}

Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
    throw (uno::RuntimeException)
{
    vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexColumnLabels() );
    SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
    return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
}

// ____ XChartData (base of XChartDataArray) ____
void SAL_CALL InternalDataProvider::addChartDataChangeEventListener(
    const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& )
    throw (uno::RuntimeException)
{
}

void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener(
    const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& )
    throw (uno::RuntimeException)
{
}

double SAL_CALL InternalDataProvider::getNotANumber()
    throw (uno::RuntimeException)
{
    double fNan;
    ::rtl::math::setNan( & fNan );
    return fNan;
}

::sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber )
    throw (uno::RuntimeException)
{
    return ::rtl::math::isNan( nNumber )
        || ::rtl::math::isInf( nNumber );
}
// lang::XInitialization:
void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments) throw (uno::RuntimeException, uno::Exception)
{
	comphelper::SequenceAsHashMap aArgs(_aArguments);
    if ( aArgs.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),sal_False) )
		createDefaultData();
}
// ____ XCloneable ____
Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone()
    throw (uno::RuntimeException)
{
    return Reference< util::XCloneable >( new InternalDataProvider( *this ));
}


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

Sequence< OUString > InternalDataProvider::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 1 );
    aServices[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.data.DataProvider" ));
    return aServices;
}

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

APPHELPER_XSERVICEINFO_IMPL( InternalDataProvider, lcl_aServiceName );

} //  namespace chart
