summaryrefslogtreecommitdiff
path: root/chart2/source/tools/InternalDataProvider.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/tools/InternalDataProvider.cxx')
-rw-r--r--chart2/source/tools/InternalDataProvider.cxx1314
1 files changed, 1314 insertions, 0 deletions
diff --git a/chart2/source/tools/InternalDataProvider.cxx b/chart2/source/tools/InternalDataProvider.cxx
new file mode 100644
index 000000000000..4abc51be31af
--- /dev/null
+++ b/chart2/source/tools/InternalDataProvider.cxx
@@ -0,0 +1,1314 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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;
+
+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( xLabel->getTextualData() ) );
+ else
+ m_rInternalData.setComplexRowLabel( nNewIndex, ContainerHelper::SequenceToVector( 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_makeAnyFromLevelVector : public ::std::unary_function< vector< OUString >, uno::Any >
+{
+public:
+
+ explicit lcl_makeAnyFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ uno::Any operator() ( const vector< OUString >& rVector )
+ {
+ OUString aString;
+ if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
+ aString = rVector[m_nLevel];
+ return uno::makeAny( aString );
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_getStringFromLevelVector : public ::std::unary_function< vector< OUString >, OUString >
+{
+public:
+
+ explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ OUString operator() ( const vector< OUString >& rVector )
+ {
+ OUString aString;
+ if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
+ aString = rVector[m_nLevel];
+ return aString;
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+
+struct lcl_setStringAtLevel : public ::std::binary_function< vector< OUString >, OUString, vector< OUString > >
+{
+public:
+
+ explicit lcl_setStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ vector< OUString > operator() ( const vector< OUString >& rVector, const OUString& rNewText )
+ {
+ vector< OUString > aRet( rVector );
+ if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
+ aRet.resize( m_nLevel+1 );
+ aRet[ m_nLevel ]=rNewText;
+ return aRet;
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_insertStringAtLevel : public ::std::unary_function< vector< OUString >, void >
+{
+public:
+
+ explicit lcl_insertStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ void operator() ( vector< OUString >& rVector )
+ {
+ if( m_nLevel > static_cast< sal_Int32 >(rVector.size()) )
+ rVector.resize( m_nLevel );
+
+ vector< OUString >::iterator aIt( rVector.begin() );
+ for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++)
+ {
+ if( nN==m_nLevel )
+ break;
+ }
+ rVector.insert( aIt, OUString() );
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_removeStringAtLevel : public ::std::unary_function< vector< OUString >, void >
+{
+public:
+
+ explicit lcl_removeStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ void operator() ( vector< OUString >& rVector )
+ {
+ vector< OUString >::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;
+};
+
+vector< OUString > lcl_AnyToStringVector( const Sequence< uno::Any >& aAnySeq )
+{
+ vector< OUString > aStringVec;
+ transform( aAnySeq.getConstArray(), aAnySeq.getConstArray() + aAnySeq.getLength(),
+ back_inserter( aStringVec ), CommonFunctors::AnyToString() );
+ return aStringVec;
+}
+
+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;
+}
+
+} // anonymous namespace
+
+// ================================================================================
+
+InternalDataProvider::InternalDataProvider( const Reference< uno::XComponentContext > & /*_xContext*/)
+ : m_bDataInColumns( true )
+{}
+
+InternalDataProvider::InternalDataProvider( const Reference< chart2::XChartDocument > & xChartDoc, bool bConnectToModel )
+ : m_bDataInColumns( true )
+{
+ 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;
+ DataSourceHelper::detectRangeSegmentation( xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories );
+ }
+
+ // categories
+ {
+ vector< vector< OUString > > 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;
+ Reference< chart2::data::XTextualDataSequence > xSeq( xLDS->getValues(), uno::UNO_QUERY );
+ Sequence< OUString > aStringSeq;
+ if( xSeq.is() )
+ aStringSeq = xSeq->getTextualData(); // @todo: be able to deal with XDataSequence, too
+ sal_Int32 nLength = aStringSeq.getLength();
+ if( static_cast< sal_Int32 >(aNewCategories.size()) < nLength )
+ aNewCategories.resize( nLength );
+
+ transform( aNewCategories.begin(), aNewCategories.end(), aStringSeq.getConstArray(),
+ aNewCategories.begin(), lcl_setStringAtLevel(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< OUString > aStringVector(1);
+ aStringVector[0] = aSimplecategories[nN];
+ aNewCategories.push_back( aStringVector );
+ }
+ }
+ }
+
+ 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< OUString > >& rLabels )
+{
+ sal_Int32 nCount = 1;//minimum is 1!
+ vector< vector< OUString > >::const_iterator aLevelIt( rLabels.begin() );
+ vector< vector< OUString > >::const_iterator aLevelEnd( rLabels.end() );
+ for( ;aLevelIt!=aLevelEnd; ++aLevelIt )
+ {
+ const vector< ::rtl::OUString >& 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< OUString > > 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 implmented 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.getLength())
+ {
+ // 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 implmented 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< OUString > aComplexLabel = m_bDataInColumns
+ ? m_aInternalData.getComplexColumnLabel( nIndex )
+ : m_aInternalData.getComplexRowLabel( nIndex );
+ if( !aComplexLabel.empty() )
+ {
+ aResult.realloc( aComplexLabel.size() );
+ transform( aComplexLabel.begin(), aComplexLabel.end(),
+ aResult.getArray(), CommonFunctors::makeAny< OUString >());
+ }
+ }
+ else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
+ {
+ sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesPointRangeNamePrefix.getLength() ).toInt32();
+ vector< OUString > aComplexCategory = m_bDataInColumns
+ ? m_aInternalData.getComplexRowLabel( nPointIndex )
+ : m_aInternalData.getComplexColumnLabel( nPointIndex );
+ if( !aComplexCategory.empty() )
+ {
+ aResult.realloc( aComplexCategory.size() );
+ transform( aComplexCategory.begin(), aComplexCategory.end(),
+ aResult.getArray(), CommonFunctors::makeAny< OUString >());
+ }
+ }
+ else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
+ {
+ sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength() ).toInt32();
+ vector< vector< OUString > > 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_makeAnyFromLevelVector(nLevel) );
+ }
+ }
+ else if( aRange.equals( lcl_aCategoriesRangeName ) )
+ {
+ 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)
+{
+ if( aRange.match( lcl_aLabelRangePrefix ) )
+ {
+ vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) );
+ sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32();
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexColumnLabel( nIndex, aNewStrings );
+ else
+ m_aInternalData.setComplexRowLabel( nIndex, aNewStrings );
+ }
+ else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
+ {
+ vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) );
+ sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32();
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabel( nPointIndex, aNewStrings );
+ else
+ m_aInternalData.setComplexColumnLabel( nPointIndex, aNewStrings );
+ }
+ else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
+ {
+ vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) );
+ sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32();
+ vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
+
+ //ensure equal length
+ if( aNewStrings.size() > aComplexCategories.size() )
+ aComplexCategories.resize( aNewStrings.size() );
+ else if( aNewStrings.size() < aComplexCategories.size() )
+ aNewStrings.resize( aComplexCategories.size() );
+
+ transform( aComplexCategories.begin(), aComplexCategories.end(), aNewStrings.begin(),
+ aComplexCategories.begin(), lcl_setStringAtLevel(nLevel) );
+
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( aComplexCategories );
+ else
+ m_aInternalData.setComplexColumnLabels( aComplexCategories );
+ }
+ else if( aRange.equals( lcl_aCategoriesRangeName ) )
+ {
+ if( m_bDataInColumns )
+ this->setRowDescriptions( lcl_AnyToStringSequence(aNewData) );
+ else
+ this->setColumnDescriptions( lcl_AnyToStringSequence(aNewData) );
+ }
+ 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< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
+ ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertStringAtLevel(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< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
+ ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeStringAtLevel(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 implmented 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
+{
+Sequence< Sequence< OUString > > lcl_convertComplexVectorToSequence( const vector< vector< OUString > >& 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]=ContainerHelper::ContainerToSequence( rIn[nN] );
+ }
+ return aRet;
+}
+
+vector< vector< OUString > > lcl_convertComplexSequenceToVector( const Sequence< Sequence< OUString > >& rIn )
+{
+ vector< vector< OUString > > aRet;
+ sal_Int32 nOuterCount = rIn.getLength();
+ for( sal_Int32 nN=0; nN<nOuterCount; nN++)
+ aRet.push_back( ContainerHelper::SequenceToVector( rIn[nN] ) );
+ return aRet;
+}
+
+class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider
+{
+public:
+
+ explicit SplitCategoriesProvider_ForComplexDescriptions( const ::std::vector< ::std::vector< ::rtl::OUString > >& 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< ::rtl::OUString > >& 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
+
+// ____ XComplexDescriptionAccess ____
+Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions() throw (uno::RuntimeException)
+{
+ return lcl_convertComplexVectorToSequence( m_aInternalData.getComplexRowLabels() );
+}
+void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aRowDescriptions ) throw (uno::RuntimeException)
+{
+ m_aInternalData.setComplexRowLabels( lcl_convertComplexSequenceToVector(aRowDescriptions) );
+}
+Sequence< Sequence< ::rtl::OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions() throw (uno::RuntimeException)
+{
+ return lcl_convertComplexVectorToSequence( m_aInternalData.getComplexColumnLabels() );
+}
+void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aColumnDescriptions ) throw (uno::RuntimeException)
+{
+ m_aInternalData.setComplexColumnLabels( lcl_convertComplexSequenceToVector(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< OUString > > aComplexDescriptions( aRowDescriptions.getLength() );
+ transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(),
+ aComplexDescriptions.begin(), lcl_setStringAtLevel(0) );
+ m_aInternalData.setComplexRowLabels( aComplexDescriptions );
+}
+
+void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
+ throw (uno::RuntimeException)
+{
+ vector< vector< OUString > > aComplexDescriptions( aColumnDescriptions.getLength() );
+ transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(),
+ aComplexDescriptions.begin(), lcl_setStringAtLevel(0) );
+ m_aInternalData.setComplexColumnLabels( aComplexDescriptions );
+}
+
+Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
+ throw (uno::RuntimeException)
+{
+ vector< vector< OUString > > aComplexLabels( m_aInternalData.getComplexRowLabels() );
+ SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
+ return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
+}
+
+Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
+ throw (uno::RuntimeException)
+{
+ vector< vector< OUString > > 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