1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <rtl/math.hxx>
21 
22 #include <iterator>
23 
24 #include <InternalDataProvider.hxx>
25 #include <LabeledDataSequence.hxx>
26 #include <DataSource.hxx>
27 #include <XMLRangeHelper.hxx>
28 #include <CommonFunctors.hxx>
29 #include <UncachedDataSequence.hxx>
30 #include <DataSourceHelper.hxx>
31 #include <ChartModel.hxx>
32 #include <ChartModelHelper.hxx>
33 #include <DiagramHelper.hxx>
34 #include <ExplicitCategoriesProvider.hxx>
35 
36 #include <com/sun/star/chart2/data/XDataSequence.hpp>
37 #include <com/sun/star/chart/ChartDataRowSource.hpp>
38 #include <cppuhelper/supportsservice.hxx>
39 #include <comphelper/sequenceashashmap.hxx>
40 #include <comphelper/property.hxx>
41 #include <tools/diagnose_ex.h>
42 
43 #include <vector>
44 #include <algorithm>
45 
46 namespace com::sun::star::chart2 { class XChartDocument; }
47 
48 using namespace ::com::sun::star;
49 using namespace ::std;
50 
51 using ::com::sun::star::uno::Reference;
52 using ::com::sun::star::uno::Sequence;
53 
54 namespace chart
55 {
56 
57 namespace
58 {
59 
60 constexpr OUStringLiteral lcl_aCategoriesRangeName = u"categories";
61 const char lcl_aCategoriesLevelRangeNamePrefix[] = "categoriesL "; //L <-> level
62 const char lcl_aCategoriesPointRangeNamePrefix[] = "categoriesP "; //P <-> point
63 constexpr OUStringLiteral lcl_aCategoriesRoleName = u"categories";
64 const char lcl_aLabelRangePrefix[] = "label ";
65 constexpr OUStringLiteral lcl_aCompleteRange = u"all";
66 
67 typedef std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > >
68     lcl_tSequenceMap;
69 
lcl_AnyToStringSequence(const std::vector<uno::Any> & aAnySeq)70 std::vector< OUString > lcl_AnyToStringSequence( const std::vector< uno::Any >& aAnySeq )
71 {
72     std::vector< OUString > aResult;
73     aResult.resize( aAnySeq.size() );
74     int i = 0;
75     for (const uno::Any& aAny : aAnySeq)
76        aResult[i++] = CommonFunctors::AnyToString()(aAny);
77     return aResult;
78 }
79 
lcl_StringToAnyVector(const css::uno::Sequence<OUString> & aStringSeq)80 std::vector< uno::Any > lcl_StringToAnyVector( const css::uno::Sequence< OUString >& aStringSeq )
81 {
82     std::vector< uno::Any > aResult;
83     aResult.resize( aStringSeq.getLength() );
84     int i = 0;
85     for (const OUString& aStr : aStringSeq)
86        aResult[i++] = CommonFunctors::makeAny<OUString>()(aStr);
87     return aResult;
88 }
89 
90 struct lcl_setModified
91 {
operator ()chart::__anon1db070c30111::lcl_setModified92     void operator() ( const lcl_tSequenceMap::value_type & rMapEntry )
93     {
94         // convert weak reference to reference
95         Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second );
96         if( xSeq.is())
97         {
98             Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY );
99             if( xMod.is())
100                 xMod->setModified( true );
101         }
102     }
103 };
104 
105 struct lcl_internalizeSeries
106 {
lcl_internalizeSerieschart::__anon1db070c30111::lcl_internalizeSeries107     lcl_internalizeSeries( InternalData & rInternalData,
108                            InternalDataProvider & rProvider,
109                            bool bConnectToModel, bool bDataInColumns ) :
110             m_rInternalData( rInternalData ),
111             m_rProvider( rProvider ),
112             m_bConnectToModel( bConnectToModel ),
113             m_bDataInColumns( bDataInColumns )
114     {}
operator ()chart::__anon1db070c30111::lcl_internalizeSeries115     void operator() ( const Reference< chart2::XDataSeries > & xSeries )
116     {
117         Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
118         Reference< chart2::data::XDataSink >   xSink(   xSeries, uno::UNO_QUERY );
119         if( !(xSource.is() && xSink.is()) )
120             return;
121 
122         Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeriesData = xSource->getDataSequences();
123         Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.getLength() );
124         for( sal_Int32 i=0; i<aOldSeriesData.getLength(); ++i )
125         {
126             sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() );
127             OUString aIdentifier( OUString::number( nNewIndex ));
128             //@todo: deal also with genericXDataSequence
129             Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY );
130             Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY );
131             Reference< chart2::data::XDataSequence > xNewValues;
132 
133             if( xValues.is() )
134             {
135                 auto aValues( comphelper::sequenceToContainer<std::vector< double >>( xValues->getNumericalData()));
136                 if( m_bDataInColumns )
137                     m_rInternalData.setColumnValues( nNewIndex, aValues );
138                 else
139                     m_rInternalData.setRowValues( nNewIndex, aValues );
140                 if( m_bConnectToModel )
141                 {
142                     xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier ));
143                     comphelper::copyProperties(
144                         Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ),
145                         Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY ));
146                 }
147             }
148 
149             if( xLabel.is() )
150             {
151                 if( m_bDataInColumns )
152                     m_rInternalData.setComplexColumnLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
153                 else
154                     m_rInternalData.setComplexRowLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
155                 if( m_bConnectToModel )
156                 {
157                     Reference< chart2::data::XDataSequence > xNewLabel(
158                         m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier ));
159                     comphelper::copyProperties(
160                         Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ),
161                         Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY ));
162                     aNewSeriesData[i].set( new LabeledDataSequence( xNewValues, xNewLabel ) );
163                 }
164             }
165             else
166             {
167                 if( m_bConnectToModel )
168                     aNewSeriesData[i].set( new LabeledDataSequence( xNewValues ) );
169             }
170         }
171         if( m_bConnectToModel )
172             xSink->setData( aNewSeriesData );
173      }
174 
175 private:
176     InternalData &          m_rInternalData;
177     InternalDataProvider &  m_rProvider;
178     bool                    m_bConnectToModel;
179     bool                    m_bDataInColumns;
180 };
181 
182 struct lcl_copyFromLevel
183 {
184 public:
185 
lcl_copyFromLevelchart::__anon1db070c30111::lcl_copyFromLevel186     explicit lcl_copyFromLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
187     {}
188 
operator ()chart::__anon1db070c30111::lcl_copyFromLevel189     uno::Any operator() ( const vector< uno::Any >& rVector )
190     {
191         uno::Any aRet;
192         if( m_nLevel <  static_cast< sal_Int32 >(rVector.size()) )
193             aRet = rVector[m_nLevel];
194         return aRet;
195     }
196 
197 private:
198     sal_Int32 m_nLevel;
199 };
200 
201 struct lcl_getStringFromLevelVector
202 {
203 public:
204 
lcl_getStringFromLevelVectorchart::__anon1db070c30111::lcl_getStringFromLevelVector205     explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
206     {}
207 
operator ()chart::__anon1db070c30111::lcl_getStringFromLevelVector208     OUString operator() ( const vector< uno::Any >& rVector )
209     {
210         OUString aString;
211         if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
212             aString = CommonFunctors::AnyToString()(rVector[m_nLevel]);
213         return aString;
214     }
215 
216 private:
217     sal_Int32 m_nLevel;
218 };
219 
220 struct lcl_setAnyAtLevel
221 {
222 public:
223 
lcl_setAnyAtLevelchart::__anon1db070c30111::lcl_setAnyAtLevel224     explicit lcl_setAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
225     {}
226 
operator ()chart::__anon1db070c30111::lcl_setAnyAtLevel227     vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const uno::Any& rNewValue )
228     {
229         vector< uno::Any > aRet( rVector );
230         if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
231             aRet.resize( m_nLevel+1 );
232         aRet[ m_nLevel ]=rNewValue;
233         return aRet;
234     }
235 
236 private:
237     sal_Int32 m_nLevel;
238 };
239 
240 struct lcl_setAnyAtLevelFromStringSequence
241 {
242 public:
243 
lcl_setAnyAtLevelFromStringSequencechart::__anon1db070c30111::lcl_setAnyAtLevelFromStringSequence244     explicit lcl_setAnyAtLevelFromStringSequence( sal_Int32 nLevel ) : m_nLevel( nLevel )
245     {}
246 
operator ()chart::__anon1db070c30111::lcl_setAnyAtLevelFromStringSequence247     vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const OUString& rNewValue )
248     {
249         vector< uno::Any > aRet( rVector );
250         if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
251             aRet.resize( m_nLevel+1 );
252         aRet[ m_nLevel ] <<= rNewValue;
253         return aRet;
254     }
255 
256 private:
257     sal_Int32 m_nLevel;
258 };
259 
260 struct lcl_insertAnyAtLevel
261 {
262 public:
263 
lcl_insertAnyAtLevelchart::__anon1db070c30111::lcl_insertAnyAtLevel264     explicit lcl_insertAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
265     {}
266 
operator ()chart::__anon1db070c30111::lcl_insertAnyAtLevel267     void operator() ( vector< uno::Any >& rVector )
268     {
269         if( m_nLevel >= static_cast< sal_Int32 >(rVector.size()) )
270         {
271             rVector.resize( m_nLevel + 1 );
272         }
273         else
274         {
275             rVector.insert( rVector.begin() + m_nLevel, uno::Any() );
276         }
277     }
278 
279 private:
280     sal_Int32 m_nLevel;
281 };
282 
283 struct lcl_removeAnyAtLevel
284 {
285 public:
286 
lcl_removeAnyAtLevelchart::__anon1db070c30111::lcl_removeAnyAtLevel287     explicit lcl_removeAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
288     {}
289 
operator ()chart::__anon1db070c30111::lcl_removeAnyAtLevel290     void operator() ( vector< uno::Any >& rVector )
291     {
292         if( m_nLevel < static_cast<sal_Int32>(rVector.size()) )
293         {
294             rVector.erase(rVector.begin() + m_nLevel);
295         }
296     }
297 
298 private:
299     sal_Int32 m_nLevel;
300 };
301 
302 } // anonymous namespace
303 
InternalDataProvider()304 InternalDataProvider::InternalDataProvider()
305     : m_bDataInColumns( true )
306 {}
307 
InternalDataProvider(const Reference<chart2::XChartDocument> & xChartDoc,bool bConnectToModel,bool bDefaultDataInColumns)308 InternalDataProvider::InternalDataProvider(
309     const Reference< chart2::XChartDocument > & xChartDoc,
310     bool bConnectToModel,
311     bool bDefaultDataInColumns)
312 :   m_bDataInColumns( bDefaultDataInColumns )
313 {
314     try
315     {
316         Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) );
317         if( xDiagram.is())
318         {
319             Reference< frame::XModel > xChartModel = xChartDoc;
320 
321             //data in columns?
322             {
323                 OUString aRangeString;
324                 bool bFirstCellAsLabel = true;
325                 bool bHasCategories = true;
326                 uno::Sequence< sal_Int32 > aSequenceMapping;
327                 const bool bSomethingDetected(
328                     DataSourceHelper::detectRangeSegmentation(
329                         xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ));
330 
331                 // #i120559# if no data was available, restore default
332                 if(!bSomethingDetected && m_bDataInColumns != bDefaultDataInColumns)
333                 {
334                     m_bDataInColumns = bDefaultDataInColumns;
335                 }
336             }
337 
338             // categories
339             {
340                 vector< vector< uno::Any > > aNewCategories;//inner count is level
341                 {
342                     ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartModel);
343                     ExplicitCategoriesProvider aExplicitCategoriesProvider(ChartModelHelper::getFirstCoordinateSystem(xChartModel), rModel);
344 
345                     const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() );
346                     sal_Int32 nLevelCount = rSplitCategoriesList.getLength();
347                     for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
348                     {
349                         Reference< chart2::data::XLabeledDataSequence > xLDS( rSplitCategoriesList[nL] );
350                         if( !xLDS.is() )
351                             continue;
352                         Sequence< uno::Any > aDataSeq;
353                         Reference< chart2::data::XDataSequence > xSeq( xLDS->getValues() );
354                         if( xSeq.is() )
355                             aDataSeq = xSeq->getData();
356                         sal_Int32 nLength = aDataSeq.getLength();
357                         sal_Int32 nCatLength = static_cast< sal_Int32 >(aNewCategories.size());
358                         if( nCatLength < nLength )
359                             aNewCategories.resize( nLength );
360                         else if( nLength < nCatLength )
361                             aDataSeq.realloc( nCatLength );
362                         transform( aNewCategories.begin(), aNewCategories.end(), aDataSeq.getConstArray(),
363                             aNewCategories.begin(), lcl_setAnyAtLevel(nL) );
364                     }
365                     if( !nLevelCount )
366                     {
367                         Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories();
368                         sal_Int32 nLength = aSimplecategories.getLength();
369                         aNewCategories.reserve( nLength );
370                         for( sal_Int32 nN=0; nN<nLength; nN++)
371                         {
372                             aNewCategories.push_back( { uno::Any(aSimplecategories[nN]) } );
373                         }
374                     }
375                 }
376 
377                 if( m_bDataInColumns )
378                     m_aInternalData.setComplexRowLabels( aNewCategories );
379                 else
380                     m_aInternalData.setComplexColumnLabels( aNewCategories );
381                 if( bConnectToModel )
382                     DiagramHelper::setCategoriesToDiagram( new LabeledDataSequence(
383                         createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), xDiagram );
384             }
385 
386             // data series
387             std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc ));
388             lcl_internalizeSeries ftor( m_aInternalData, *this, bConnectToModel, m_bDataInColumns );
389             for( const auto& rxScreen : aSeriesVector )
390                 ftor( rxScreen );
391         }
392     }
393     catch( const uno::Exception & )
394     {
395         DBG_UNHANDLED_EXCEPTION("chart2");
396     }
397 }
398 
399 // copy-CTOR
InternalDataProvider(const InternalDataProvider & rOther)400 InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) :
401         impl::InternalDataProvider_Base(rOther),
402         m_aSequenceMap( rOther.m_aSequenceMap ),
403         m_aInternalData( rOther.m_aInternalData ),
404         m_bDataInColumns( rOther.m_bDataInColumns )
405 {}
406 
~InternalDataProvider()407 InternalDataProvider::~InternalDataProvider()
408 {}
409 
addDataSequenceToMap(const OUString & rRangeRepresentation,const Reference<chart2::data::XDataSequence> & xSequence)410 void InternalDataProvider::addDataSequenceToMap(
411     const OUString & rRangeRepresentation,
412     const Reference< chart2::data::XDataSequence > & xSequence )
413 {
414     m_aSequenceMap.emplace(
415             rRangeRepresentation,
416             uno::WeakReference< chart2::data::XDataSequence >( xSequence ));
417 }
418 
deleteMapReferences(const OUString & rRangeRepresentation)419 void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresentation )
420 {
421     // set sequence to deleted by setting its range to an empty string
422     tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation ));
423     for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
424     {
425         Reference< chart2::data::XDataSequence > xSeq( aIt->second );
426         if( xSeq.is())
427         {
428             Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
429             if( xNamed.is())
430                 xNamed->setName( OUString());
431         }
432     }
433     // remove from map
434     m_aSequenceMap.erase( aRange.first, aRange.second );
435 }
436 
adaptMapReferences(const OUString & rOldRangeRepresentation,const OUString & rNewRangeRepresentation)437 void InternalDataProvider::adaptMapReferences(
438     const OUString & rOldRangeRepresentation,
439     const OUString & rNewRangeRepresentation )
440 {
441     tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation ));
442     tSequenceMap aNewElements;
443     for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
444     {
445         Reference< chart2::data::XDataSequence > xSeq( aIt->second );
446         if( xSeq.is())
447         {
448             Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
449             if( xNamed.is())
450                 xNamed->setName( rNewRangeRepresentation );
451         }
452         aNewElements.emplace( rNewRangeRepresentation, aIt->second );
453     }
454     // erase map values for old index
455     m_aSequenceMap.erase( aRange.first, aRange.second );
456     // add new entries for values with new index
457     m_aSequenceMap.insert( aNewElements.begin(), aNewElements.end() );
458 }
459 
increaseMapReferences(sal_Int32 nBegin,sal_Int32 nEnd)460 void InternalDataProvider::increaseMapReferences(
461     sal_Int32 nBegin, sal_Int32 nEnd )
462 {
463     for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex )
464     {
465         adaptMapReferences( OUString::number( nIndex ),
466                             OUString::number( nIndex + 1 ));
467         adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
468                             lcl_aLabelRangePrefix + OUString::number( nIndex + 1 ));
469     }
470 }
471 
decreaseMapReferences(sal_Int32 nBegin,sal_Int32 nEnd)472 void InternalDataProvider::decreaseMapReferences(
473     sal_Int32 nBegin, sal_Int32 nEnd )
474 {
475     for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex )
476     {
477         adaptMapReferences( OUString::number( nIndex ),
478                             OUString::number( nIndex - 1 ));
479         adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
480                             lcl_aLabelRangePrefix + OUString::number( nIndex - 1 ));
481     }
482 }
483 
createDataSequenceAndAddToMap(const OUString & rRangeRepresentation)484 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
485     const OUString & rRangeRepresentation )
486 {
487     Reference<chart2::data::XDataSequence> xSeq = createDataSequenceFromArray(rRangeRepresentation, u"");
488     if (xSeq.is())
489         return xSeq;
490 
491     xSeq.set(new UncachedDataSequence(this, rRangeRepresentation));
492     addDataSequenceToMap(rRangeRepresentation, xSeq);
493     return xSeq;
494 }
495 
496 uno::Reference<chart2::data::XDataSequence>
createDataSequenceFromArray(const OUString & rArrayStr,std::u16string_view rRole)497 InternalDataProvider::createDataSequenceFromArray( const OUString& rArrayStr, std::u16string_view rRole )
498 {
499     if (rArrayStr.indexOf('{') != 0 || rArrayStr[rArrayStr.getLength()-1] != '}')
500     {
501         // Not an array string.
502         return uno::Reference<chart2::data::XDataSequence>();
503     }
504 
505     bool bAllNumeric = true;
506     uno::Reference<chart2::data::XDataSequence> xSeq;
507 
508     const sal_Unicode* p = rArrayStr.getStr();
509     const sal_Unicode* pEnd = p + rArrayStr.getLength();
510     const sal_Unicode* pElem = nullptr;
511     OUString aElem;
512 
513     std::vector<OUString> aRawElems;
514     ++p; // Skip the first '{'.
515     --pEnd; // Skip the last '}'.
516     bool bInQuote = false;
517     for (; p != pEnd; ++p)
518     {
519         // Skip next "" within the title text: it's an escaped double quotation mark.
520         if (bInQuote && *p == '"' && *(p + 1) == '"')
521         {
522             if (!pElem)
523                 pElem = p;
524             ++p;
525         }
526         else if (*p == '"')
527         {
528             bInQuote = !bInQuote;
529             if (bInQuote)
530             {
531                 // Opening quote.
532                 pElem = nullptr;
533             }
534             else
535             {
536                 // Closing quote.
537                 if (pElem)
538                     aElem = OUString(pElem, p-pElem);
539                 // Non empty string
540                 if (!aElem.isEmpty())
541                     bAllNumeric = false;
542                 // Restore also escaped double quotation marks
543                 aRawElems.push_back(aElem.replaceAll("\"\"", "\""));
544                 pElem = nullptr;
545                 aElem.clear();
546 
547                 ++p; // Skip '"'.
548                 if (p == pEnd)
549                     break;
550             }
551         }
552         else if (*p == ';' && !bInQuote)
553         {
554             // element separator.
555             if (pElem)
556                 aElem = OUString(pElem, p-pElem);
557             aRawElems.push_back(aElem);
558             pElem = nullptr;
559             aElem.clear();
560         }
561         else if (!pElem)
562             pElem = p;
563     }
564 
565     if (pElem)
566     {
567         aElem = OUString(pElem, p-pElem);
568         aRawElems.push_back(aElem);
569     }
570 
571     if (rRole == u"values-y" || rRole == u"values-first" || rRole == u"values-last" ||
572         rRole == u"values-min" || rRole == u"values-max" || rRole == u"values-size")
573     {
574         // Column values.  Append a new data column and populate it.
575 
576         std::vector<double> aValues;
577         aValues.reserve(aRawElems.size());
578         for (const OUString & aRawElem : aRawElems)
579         {
580             if (aRawElem.isEmpty())
581                 aValues.push_back(NAN);
582             else
583                 aValues.push_back(aRawElem.toDouble());
584         }
585         sal_Int32 n = m_aInternalData.appendColumn();
586 
587         m_aInternalData.setColumnValues(n, aValues);
588 
589         OUString aRangeRep = OUString::number(n);
590         xSeq.set(new UncachedDataSequence(this, aRangeRep));
591         addDataSequenceToMap(aRangeRep, xSeq);
592     }
593     else if (rRole == u"values-x")
594     {
595         std::vector<double> aValues;
596         aValues.reserve(aRawElems.size());
597         if (bAllNumeric)
598         {
599             for (const OUString & aRawElem : aRawElems)
600             {
601                 if (!aRawElem.isEmpty())
602                     aValues.push_back(aRawElem.toDouble());
603                 else
604                     aValues.push_back(NAN);
605             }
606         }
607         else
608         {
609             for (size_t i = 0; i < aRawElems.size(); ++i)
610                 aValues.push_back(i+1);
611         }
612 
613         sal_Int32 n = m_aInternalData.appendColumn();
614         m_aInternalData.setColumnValues(n, aValues);
615 
616         OUString aRangeRep = OUString::number(n);
617         xSeq.set(new UncachedDataSequence(this, aRangeRep));
618         addDataSequenceToMap(aRangeRep, xSeq);
619     }
620     else if (rRole == u"categories")
621     {
622         // Category labels.
623 
624         for (size_t i = 0; i < aRawElems.size(); ++i)
625         {
626             std::vector<uno::Any> aLabels(1, uno::Any(aRawElems[i]));
627             m_aInternalData.setComplexRowLabel(i, aLabels);
628         }
629 
630         xSeq.set(new UncachedDataSequence(this, lcl_aCategoriesRangeName));
631         addDataSequenceToMap(lcl_aCategoriesRangeName, xSeq);
632     }
633     else if (rRole == u"label")
634     {
635         // Data series label.  There should be only one element.  This always
636         // goes to the last data column.
637         sal_Int32 nColSize = m_aInternalData.getColumnCount();
638         if (!aRawElems.empty() && nColSize)
639         {
640             std::vector<uno::Any> aLabels(1, uno::Any(aRawElems[0]));
641             m_aInternalData.setComplexColumnLabel(nColSize-1, aLabels);
642 
643             OUString aRangeRep = lcl_aLabelRangePrefix + OUString::number(nColSize-1);
644             xSeq.set(new UncachedDataSequence(this, aRangeRep));
645             addDataSequenceToMap(aRangeRep, xSeq);
646         }
647     }
648 
649     return xSeq;
650 }
651 
createDataSequenceAndAddToMap(const OUString & rRangeRepresentation,const OUString & rRole)652 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
653     const OUString & rRangeRepresentation,
654     const OUString & rRole )
655 {
656     Reference< chart2::data::XDataSequence > xSeq(
657         new UncachedDataSequence( this, rRangeRepresentation, rRole ));
658     addDataSequenceToMap( rRangeRepresentation, xSeq );
659     return xSeq;
660 }
661 
662 // ____ XDataProvider ____
createDataSourcePossible(const Sequence<beans::PropertyValue> &)663 sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ )
664 {
665     return true;
666 }
667 
668 namespace
669 {
670 
lcl_getInnerLevelCount(const vector<vector<uno::Any>> & rLabels)671 sal_Int32 lcl_getInnerLevelCount( const vector< vector< uno::Any > >& rLabels )
672 {
673     sal_Int32 nCount = 1;//minimum is 1!
674     for (auto const& elemLabel : rLabels)
675     {
676         nCount = std::max<sal_Int32>( elemLabel.size(), nCount );
677     }
678     return nCount;
679 }
680 
681 }//end anonymous namespace
682 
createDataSource(const Sequence<beans::PropertyValue> & aArguments)683 Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource(
684     const Sequence< beans::PropertyValue >& aArguments )
685 {
686     OUString aRangeRepresentation;
687     bool bUseColumns = true;
688     bool bFirstCellAsLabel = true;
689     bool bHasCategories = true;
690     uno::Sequence< sal_Int32 > aSequenceMapping;
691     DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
692 
693     if( aRangeRepresentation == lcl_aCategoriesRangeName )
694     {
695         //return split complex categories if we have any:
696         std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories;
697         vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
698         if( bUseColumns==m_bDataInColumns )
699         {
700             sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
701             for( sal_Int32 nL=0; nL<nLevelCount; nL++ )
702                 aComplexCategories.push_back( new LabeledDataSequence(
703                     new UncachedDataSequence( this
704                         , lcl_aCategoriesLevelRangeNamePrefix + OUString::number( nL )
705                         , lcl_aCategoriesRoleName ) ) );
706         }
707         else
708         {
709             sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount();
710             for( sal_Int32 nP=0; nP<nPointCount; nP++ )
711                 aComplexCategories.push_back( new LabeledDataSequence(
712                     new UncachedDataSequence( this
713                         , lcl_aCategoriesPointRangeNamePrefix + OUString::number( nP )
714                         , lcl_aCategoriesRoleName ) ) );
715         }
716         //don't add the created sequences to the map as they are used temporarily only ...
717         return new DataSource( comphelper::containerToSequence(aComplexCategories) );
718     }
719 
720     OSL_ASSERT( aRangeRepresentation == lcl_aCompleteRange );
721 
722     std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec;
723 
724     // categories
725     if( bHasCategories )
726         aResultLSeqVec.push_back(
727             new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) );
728 
729     // data with labels
730     std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec;
731     const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount());
732     aDataVec.reserve(nCount);
733     for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
734     {
735         aDataVec.push_back(
736             new LabeledDataSequence(
737                 createDataSequenceAndAddToMap( OUString::number( nIdx )),
738                 createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIdx ))));
739     }
740 
741     // attention: this data provider has the limitation that it stores
742     // internally if data comes from columns or rows. It is intended for
743     // creating only one used data source.
744     // @todo: add this information in the range representation strings
745     m_bDataInColumns = bUseColumns;
746 
747     //reorder labeled sequences according to aSequenceMapping; ignore categories
748     for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
749     {
750         std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex];
751         if( nOldIndex < aDataVec.size() )
752         {
753             if( aDataVec[nOldIndex].is() )
754             {
755                 aResultLSeqVec.push_back( aDataVec[nOldIndex] );
756                 aDataVec[nOldIndex] = nullptr;
757             }
758         }
759     }
760 
761     //add left over data sequences to result
762     for (auto const& elem : aDataVec)
763     {
764         if( elem.is() )
765             aResultLSeqVec.push_back(elem);
766     }
767 
768     return new DataSource( comphelper::containerToSequence(aResultLSeqVec) );
769 }
770 
detectArguments(const Reference<chart2::data::XDataSource> &)771 Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments(
772     const Reference< chart2::data::XDataSource >& /* xDataSource */ )
773 {
774     Sequence< beans::PropertyValue > aArguments( 4 );
775     aArguments[0] = beans::PropertyValue(
776         "CellRangeRepresentation", -1, uno::Any( OUString(lcl_aCompleteRange) ),
777         beans::PropertyState_DIRECT_VALUE );
778     aArguments[1] = beans::PropertyValue(
779         "DataRowSource", -1, uno::Any(
780             m_bDataInColumns
781             ? css::chart::ChartDataRowSource_COLUMNS
782             : css::chart::ChartDataRowSource_ROWS ),
783         beans::PropertyState_DIRECT_VALUE );
784     // internal data always contains labels and categories
785     aArguments[2] = beans::PropertyValue(
786         "FirstCellAsLabel", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE );
787     aArguments[3] = beans::PropertyValue(
788         "HasCategories", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE );
789 
790     // #i85913# Sequence Mapping is not needed for internal data, as it is
791     // applied to the data when the data source is created.
792 
793     return aArguments;
794 }
795 
createDataSequenceByRangeRepresentationPossible(const OUString &)796 sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
797 {
798     return true;
799 }
800 
createDataSequenceByRangeRepresentation(const OUString & aRangeRepresentation)801 Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation(
802     const OUString& aRangeRepresentation )
803 {
804     if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
805     {
806         OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
807 
808         // categories
809         return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
810     }
811     else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
812     {
813         // label
814         sal_Int32 nIndex = aRangeRepresentation.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
815         return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIndex ));
816     }
817     else if ( aRangeRepresentation == "last" )
818     {
819         sal_Int32 nIndex = (m_bDataInColumns
820                             ? m_aInternalData.getColumnCount()
821                             : m_aInternalData.getRowCount()) - 1;
822         return createDataSequenceAndAddToMap( OUString::number( nIndex ));
823     }
824     else if( !aRangeRepresentation.isEmpty())
825     {
826         // data
827         return createDataSequenceAndAddToMap( aRangeRepresentation );
828     }
829 
830     return Reference< chart2::data::XDataSequence >();
831 }
832 
833 Reference<chart2::data::XDataSequence> SAL_CALL
createDataSequenceByValueArray(const OUString & aRole,const OUString & aRangeRepresentation)834 InternalDataProvider::createDataSequenceByValueArray(
835     const OUString& aRole, const OUString& aRangeRepresentation )
836 {
837     return createDataSequenceFromArray(aRangeRepresentation, aRole);
838 }
839 
getRangeSelection()840 Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection()
841 {
842     // there is no range selection component
843     return Reference< sheet::XRangeSelection >();
844 }
845 
846 // ____ XInternalDataProvider ____
hasDataByRangeRepresentation(const OUString & aRange)847 sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange )
848 {
849     bool bResult = false;
850 
851     if( aRange.match( lcl_aCategoriesRangeName ))
852     {
853         OSL_ASSERT( aRange == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
854         bResult = true;
855     }
856     else if( aRange.match( lcl_aLabelRangePrefix ))
857     {
858         sal_Int32 nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
859         bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
860     }
861     else
862     {
863         sal_Int32 nIndex = aRange.toInt32();
864         bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
865     }
866 
867     return bResult;
868 }
869 
getDataByRangeRepresentation(const OUString & aRange)870 Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange )
871 {
872     Sequence< uno::Any > aResult;
873 
874     if( aRange.match( lcl_aLabelRangePrefix ) )
875     {
876         auto nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toUInt32();
877         vector< uno::Any > aComplexLabel = m_bDataInColumns
878             ? m_aInternalData.getComplexColumnLabel( nIndex )
879             : m_aInternalData.getComplexRowLabel( nIndex );
880         if( !aComplexLabel.empty() )
881             aResult = comphelper::containerToSequence(aComplexLabel);
882     }
883     else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
884     {
885         auto nPointIndex = aRange.copy( strlen(lcl_aCategoriesPointRangeNamePrefix) ).toUInt32();
886         vector< uno::Any > aComplexCategory = m_bDataInColumns
887             ? m_aInternalData.getComplexRowLabel( nPointIndex )
888             : m_aInternalData.getComplexColumnLabel( nPointIndex );
889         if( !aComplexCategory.empty() )
890             aResult = comphelper::containerToSequence(aComplexCategory);
891     }
892     else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
893     {
894         sal_Int32 nLevel = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix) ).toInt32();
895         vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
896         if( nLevel < lcl_getInnerLevelCount( aCategories ) )
897         {
898             aResult.realloc( aCategories.size() );
899             transform( aCategories.begin(), aCategories.end(),
900                        aResult.getArray(), lcl_copyFromLevel(nLevel) );
901         }
902     }
903     else if( aRange == lcl_aCategoriesRangeName )
904     {
905         vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
906         sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
907         if( nLevelCount == 1 )
908         {
909             aResult = getDataByRangeRepresentation( lcl_aCategoriesLevelRangeNamePrefix + OUString::number( 0 ) );
910         }
911         else
912         {
913             // Maybe this 'else' part and the functions is not necessary anymore.
914             Sequence< OUString > aLabels = m_bDataInColumns ? getRowDescriptions() : getColumnDescriptions();
915             aResult.realloc( aLabels.getLength() );
916             transform( aLabels.begin(), aLabels.end(),
917                        aResult.getArray(), CommonFunctors::makeAny< OUString >() );
918         }
919     }
920     else
921     {
922         sal_Int32 nIndex = aRange.toInt32();
923         if( nIndex >= 0 )
924         {
925             Sequence< double > aData;
926             if( m_bDataInColumns )
927                 aData = m_aInternalData.getColumnValues(nIndex);
928             else
929                 aData = m_aInternalData.getRowValues(nIndex);
930             if( aData.hasElements() )
931             {
932                 aResult.realloc( aData.getLength());
933                 transform( aData.begin(), aData.end(),
934                            aResult.getArray(), CommonFunctors::makeAny< double >());
935             }
936         }
937     }
938 
939     return aResult;
940 }
941 
setDataByRangeRepresentation(const OUString & aRange,const Sequence<uno::Any> & aNewData)942 void SAL_CALL InternalDataProvider::setDataByRangeRepresentation(
943     const OUString& aRange, const Sequence< uno::Any >& aNewData )
944 {
945     auto aNewVector( comphelper::sequenceToContainer<vector< uno::Any >>(aNewData) );
946     if( aRange.match( lcl_aLabelRangePrefix ) )
947     {
948         sal_uInt32 nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
949         if( m_bDataInColumns )
950             m_aInternalData.setComplexColumnLabel( nIndex, aNewVector );
951         else
952             m_aInternalData.setComplexRowLabel( nIndex, aNewVector );
953     }
954     else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
955     {
956         sal_Int32 nPointIndex = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix)).toInt32();
957         if( m_bDataInColumns )
958             m_aInternalData.setComplexRowLabel( nPointIndex, aNewVector );
959         else
960             m_aInternalData.setComplexColumnLabel( nPointIndex, aNewVector );
961     }
962     else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
963     {
964         sal_Int32 nLevel = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix)).toInt32();
965         vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
966 
967         //ensure equal length
968         if( aNewVector.size() > aComplexCategories.size() )
969             aComplexCategories.resize( aNewVector.size() );
970         else if( aNewVector.size() < aComplexCategories.size() )
971             aNewVector.resize( aComplexCategories.size() );
972 
973         transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
974                    aComplexCategories.begin(), lcl_setAnyAtLevel(nLevel) );
975 
976         if( m_bDataInColumns )
977             m_aInternalData.setComplexRowLabels( aComplexCategories );
978         else
979             m_aInternalData.setComplexColumnLabels( aComplexCategories );
980     }
981     else if( aRange == lcl_aCategoriesRangeName )
982     {
983         vector< vector< uno::Any > > aComplexCategories;
984         aComplexCategories.resize( aNewVector.size() );
985         transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
986                             aComplexCategories.begin(), lcl_setAnyAtLevel(0) );
987         if( m_bDataInColumns )
988             m_aInternalData.setComplexRowLabels( aComplexCategories );
989         else
990             m_aInternalData.setComplexColumnLabels( aComplexCategories );
991     }
992     else
993     {
994         sal_Int32 nIndex = aRange.toInt32();
995         if( nIndex>=0 )
996         {
997             vector< double > aNewDataVec;
998             transform( aNewData.begin(), aNewData.end(),
999                        back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble());
1000             if( m_bDataInColumns )
1001                 m_aInternalData.setColumnValues( nIndex, aNewDataVec );
1002             else
1003                 m_aInternalData.setRowValues( nIndex, aNewDataVec );
1004         }
1005     }
1006 }
1007 
insertSequence(::sal_Int32 nAfterIndex)1008 void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex )
1009 {
1010     if( m_bDataInColumns )
1011     {
1012         increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount());
1013         m_aInternalData.insertColumn( nAfterIndex );
1014     }
1015     else
1016     {
1017         increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount());
1018         m_aInternalData.insertRow( nAfterIndex );
1019     }
1020 }
1021 
deleteSequence(::sal_Int32 nAtIndex)1022 void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex )
1023 {
1024     deleteMapReferences( OUString::number( nAtIndex ));
1025     deleteMapReferences( lcl_aLabelRangePrefix + OUString::number( nAtIndex ));
1026     if( m_bDataInColumns )
1027     {
1028         decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount());
1029         m_aInternalData.deleteColumn( nAtIndex );
1030     }
1031     else
1032     {
1033         decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount());
1034         m_aInternalData.deleteRow( nAtIndex );
1035     }
1036 }
1037 
appendSequence()1038 void SAL_CALL InternalDataProvider::appendSequence()
1039 {
1040     if( m_bDataInColumns )
1041         m_aInternalData.appendColumn();
1042     else
1043         m_aInternalData.appendRow();
1044 }
1045 
insertComplexCategoryLevel(sal_Int32 nLevel)1046 void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel )
1047 {
1048     OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1049     if( nLevel>0 )
1050     {
1051         vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
1052         std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertAnyAtLevel(nLevel) );
1053         if( m_bDataInColumns )
1054             m_aInternalData.setComplexRowLabels( aComplexCategories );
1055         else
1056             m_aInternalData.setComplexColumnLabels( aComplexCategories );
1057 
1058         tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1059         std::for_each( aRange.first, aRange.second, lcl_setModified());
1060     }
1061 }
deleteComplexCategoryLevel(sal_Int32 nLevel)1062 void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel )
1063 {
1064     OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1065     if( nLevel>0 )
1066     {
1067         vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
1068         std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeAnyAtLevel(nLevel) );
1069         if( m_bDataInColumns )
1070             m_aInternalData.setComplexRowLabels( aComplexCategories );
1071         else
1072             m_aInternalData.setComplexColumnLabels( aComplexCategories );
1073 
1074         tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1075         std::for_each( aRange.first, aRange.second, lcl_setModified());
1076     }
1077 }
1078 
insertDataPointForAllSequences(::sal_Int32 nAfterIndex)1079 void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex )
1080 {
1081     sal_Int32 nMaxRep = 0;
1082     if( m_bDataInColumns )
1083     {
1084         m_aInternalData.insertRow( nAfterIndex );
1085         nMaxRep = m_aInternalData.getColumnCount();
1086     }
1087     else
1088     {
1089         m_aInternalData.insertColumn( nAfterIndex );
1090         nMaxRep = m_aInternalData.getRowCount();
1091     }
1092 
1093     // notify change to all affected ranges
1094     tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
1095     tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1096     std::for_each( aBegin, aEnd, lcl_setModified());
1097 
1098     tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1099     std::for_each( aRange.first, aRange.second, lcl_setModified());
1100 }
1101 
deleteDataPointForAllSequences(::sal_Int32 nAtIndex)1102 void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex )
1103 {
1104     sal_Int32 nMaxRep = 0;
1105     if( m_bDataInColumns )
1106     {
1107         m_aInternalData.deleteRow( nAtIndex );
1108         nMaxRep = m_aInternalData.getColumnCount();
1109     }
1110     else
1111     {
1112         m_aInternalData.deleteColumn( nAtIndex );
1113         nMaxRep = m_aInternalData.getRowCount();
1114     }
1115 
1116     // notify change to all affected ranges
1117     tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
1118     tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1119     std::for_each( aBegin, aEnd, lcl_setModified());
1120 
1121     tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1122     std::for_each( aRange.first, aRange.second, lcl_setModified());
1123 }
1124 
swapDataPointWithNextOneForAllSequences(::sal_Int32 nAtIndex)1125 void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex )
1126 {
1127     if( m_bDataInColumns )
1128         m_aInternalData.swapRowWithNext( nAtIndex );
1129     else
1130         m_aInternalData.swapColumnWithNext( nAtIndex );
1131     sal_Int32 nMaxRep = (m_bDataInColumns
1132                          ? m_aInternalData.getColumnCount()
1133                          : m_aInternalData.getRowCount());
1134 
1135     // notify change to all affected ranges
1136     tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
1137     tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1138     std::for_each( aBegin, aEnd, lcl_setModified());
1139 
1140     tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1141     std::for_each( aRange.first, aRange.second, lcl_setModified());
1142 }
1143 
registerDataSequenceForChanges(const Reference<chart2::data::XDataSequence> & xSeq)1144 void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq )
1145 {
1146     if( xSeq.is())
1147         addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
1148 }
1149 
1150 // ____ XRangeXMLConversion ____
convertRangeToXML(const OUString & aRangeRepresentation)1151 OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation )
1152 {
1153     XMLRangeHelper::CellRange aRange;
1154     aRange.aTableName = "local-table";
1155 
1156     // attention: this data provider has the limitation that it stores
1157     // internally if data comes from columns or rows. It is intended for
1158     // creating only one used data source.
1159     // @todo: add this information in the range representation strings
1160     if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
1161     {
1162         OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
1163         aRange.aUpperLeft.bIsEmpty = false;
1164         if( m_bDataInColumns )
1165         {
1166             aRange.aUpperLeft.nColumn = 0;
1167             aRange.aUpperLeft.nRow = 1;
1168             aRange.aLowerRight = aRange.aUpperLeft;
1169             aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1170         }
1171         else
1172         {
1173             aRange.aUpperLeft.nColumn = 1;
1174             aRange.aUpperLeft.nRow = 0;
1175             aRange.aLowerRight = aRange.aUpperLeft;
1176             aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1177         }
1178     }
1179     else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
1180     {
1181         sal_Int32 nIndex = aRangeRepresentation.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
1182         aRange.aUpperLeft.bIsEmpty = false;
1183         aRange.aLowerRight.bIsEmpty = true;
1184         if( m_bDataInColumns )
1185         {
1186             aRange.aUpperLeft.nColumn = nIndex + 1;
1187             aRange.aUpperLeft.nRow = 0;
1188         }
1189         else
1190         {
1191             aRange.aUpperLeft.nColumn = 0;
1192             aRange.aUpperLeft.nRow = nIndex + 1;
1193         }
1194     }
1195     else if( aRangeRepresentation == lcl_aCompleteRange )
1196     {
1197         aRange.aUpperLeft.bIsEmpty = false;
1198         aRange.aLowerRight.bIsEmpty = false;
1199         aRange.aUpperLeft.nColumn = 0;
1200         aRange.aUpperLeft.nRow = 0;
1201         aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1202         aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1203     }
1204     else
1205     {
1206         sal_Int32 nIndex = aRangeRepresentation.toInt32();
1207         aRange.aUpperLeft.bIsEmpty = false;
1208         if( m_bDataInColumns )
1209         {
1210             aRange.aUpperLeft.nColumn = nIndex + 1;
1211             aRange.aUpperLeft.nRow = 1;
1212             aRange.aLowerRight = aRange.aUpperLeft;
1213             aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1214         }
1215         else
1216         {
1217             aRange.aUpperLeft.nColumn = 1;
1218             aRange.aUpperLeft.nRow = nIndex + 1;
1219             aRange.aLowerRight = aRange.aUpperLeft;
1220             aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1221         }
1222     }
1223 
1224     return XMLRangeHelper::getXMLStringFromCellRange( aRange );
1225 }
1226 
convertRangeFromXML(const OUString & aXMLRange)1227 OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange )
1228 {
1229     // Handle non-standards-conforming table:cell-range-address="PivotChart", see
1230     // <https://bugs.documentfoundation.org/show_bug.cgi?id=112783> "PIVOT CHARTS: Save produces
1231     // invalid file because of invalid cell address":
1232     if (aXMLRange == "PivotChart") {
1233         return "";
1234     }
1235 
1236     static const OUStringLiteral aPivotTableID(u"PT@");
1237     if (aXMLRange.startsWith(aPivotTableID))
1238         return aXMLRange.copy(aPivotTableID.getLength());
1239 
1240     XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange ));
1241     if( aRange.aUpperLeft.bIsEmpty )
1242     {
1243         OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" );
1244         return OUString();
1245     }
1246 
1247     // "all"
1248     if( !aRange.aLowerRight.bIsEmpty &&
1249         ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) &&
1250         ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) )
1251         return lcl_aCompleteRange;
1252 
1253     // attention: this data provider has the limitation that it stores
1254     // internally if data comes from columns or rows. It is intended for
1255     // creating only one used data source.
1256     // @todo: add this information in the range representation strings
1257 
1258     // data in columns
1259     if( m_bDataInColumns )
1260     {
1261         if( aRange.aUpperLeft.nColumn == 0 )
1262             return lcl_aCategoriesRangeName;
1263         if( aRange.aUpperLeft.nRow == 0 )
1264             return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nColumn - 1 );
1265 
1266         return OUString::number( aRange.aUpperLeft.nColumn - 1 );
1267     }
1268 
1269     // data in rows
1270     if( aRange.aUpperLeft.nRow == 0 )
1271         return lcl_aCategoriesRangeName;
1272     if( aRange.aUpperLeft.nColumn == 0 )
1273         return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nRow - 1 );
1274 
1275     return OUString::number( aRange.aUpperLeft.nRow - 1 );
1276 }
1277 
1278 namespace
1279 {
1280 
1281 template< class Type >
lcl_convertVectorVectorToSequenceSequence(const vector<vector<Type>> & rIn)1282 Sequence< Sequence< Type > > lcl_convertVectorVectorToSequenceSequence( const vector< vector< Type > >& rIn )
1283 {
1284     Sequence< Sequence< Type > > aRet;
1285     sal_Int32 nOuterCount = rIn.size();
1286     if( nOuterCount )
1287     {
1288         aRet.realloc(nOuterCount);
1289         for( sal_Int32 nN=0; nN<nOuterCount; nN++)
1290             aRet[nN]= comphelper::containerToSequence( rIn[nN] );
1291     }
1292     return aRet;
1293 }
1294 
1295 template< class Type >
lcl_convertSequenceSequenceToVectorVector(const Sequence<Sequence<Type>> & rIn)1296 vector< vector< Type > > lcl_convertSequenceSequenceToVectorVector( const Sequence< Sequence< Type > >& rIn )
1297 {
1298     vector< vector< Type > > aRet;
1299     sal_Int32 nOuterCount = rIn.getLength();
1300     if( nOuterCount )
1301     {
1302         aRet.resize(nOuterCount);
1303         for( sal_Int32 nN=0; nN<nOuterCount; nN++)
1304             aRet[nN]= comphelper::sequenceToContainer<vector< Type >>( rIn[nN] );
1305     }
1306     return aRet;
1307 }
1308 
lcl_convertComplexAnyVectorToStringSequence(const vector<vector<uno::Any>> & rIn)1309 std::vector< Sequence< OUString > > lcl_convertComplexAnyVectorToStringSequence( const vector< vector< uno::Any > >& rIn )
1310 {
1311     std::vector< Sequence< OUString > > aRet;
1312     sal_Int32 nOuterCount = rIn.size();
1313     if( nOuterCount )
1314     {
1315         aRet.resize(nOuterCount);
1316         for( sal_Int32 nN=0; nN<nOuterCount; nN++)
1317             aRet[nN] = comphelper::containerToSequence(lcl_AnyToStringSequence( rIn[nN] ));
1318     }
1319     return aRet;
1320 }
1321 
lcl_convertComplexStringSequenceToAnyVector(const Sequence<Sequence<OUString>> & rIn)1322 vector< vector< uno::Any > > lcl_convertComplexStringSequenceToAnyVector( const Sequence< Sequence< OUString > >& rIn )
1323 {
1324     vector< vector< uno::Any > > aRet;
1325     sal_Int32 nOuterCount = rIn.getLength();
1326     aRet.reserve(nOuterCount);
1327     for (sal_Int32 nN = 0; nN < nOuterCount; nN++)
1328         aRet.push_back( lcl_StringToAnyVector( rIn[nN] ) );
1329     return aRet;
1330 }
1331 
1332 class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider
1333 {
1334 public:
1335 
SplitCategoriesProvider_ForComplexDescriptions(const std::vector<std::vector<uno::Any>> & rComplexDescriptions)1336     explicit SplitCategoriesProvider_ForComplexDescriptions( const std::vector< std::vector< uno::Any > >& rComplexDescriptions )
1337         : m_rComplexDescriptions( rComplexDescriptions )
1338     {}
1339 
1340     virtual sal_Int32 getLevelCount() const override;
1341     virtual uno::Sequence< OUString > getStringsForLevel( sal_Int32 nIndex ) const override;
1342 
1343 private:
1344     const std::vector< std::vector< uno::Any > >& m_rComplexDescriptions;
1345 };
1346 
getLevelCount() const1347 sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const
1348 {
1349     return lcl_getInnerLevelCount( m_rComplexDescriptions );
1350 }
getStringsForLevel(sal_Int32 nLevel) const1351 uno::Sequence< OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const
1352 {
1353     uno::Sequence< OUString > aResult;
1354     if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) )
1355     {
1356         aResult.realloc( m_rComplexDescriptions.size() );
1357         transform( m_rComplexDescriptions.begin(), m_rComplexDescriptions.end(),
1358                    aResult.getArray(), lcl_getStringFromLevelVector(nLevel) );
1359     }
1360     return aResult;
1361 }
1362 
1363 }//anonymous namespace
1364 
1365 // ____ XDateCategories ____
getDateCategories()1366 Sequence< double > SAL_CALL InternalDataProvider::getDateCategories()
1367 {
1368     double fNan = InternalDataProvider::getNotANumber();
1369     double fValue = fNan;
1370     vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
1371     sal_Int32 nCount = aCategories.size();
1372     Sequence< double > aDoubles( nCount );
1373     sal_Int32 nN=0;
1374     for (auto const& category : aCategories)
1375     {
1376         if( category.empty() || !(category[0]>>=fValue) )
1377             fValue = fNan;
1378         aDoubles[nN++]=fValue;
1379     }
1380     return aDoubles;
1381 }
1382 
setDateCategories(const Sequence<double> & rDates)1383 void SAL_CALL InternalDataProvider::setDateCategories( const Sequence< double >& rDates )
1384 {
1385     sal_Int32 nCount = rDates.getLength();
1386     vector< vector< uno::Any > > aNewCategories;
1387     aNewCategories.reserve(nCount);
1388     vector< uno::Any > aSingleLabel(1);
1389 
1390     for(sal_Int32 nN=0; nN<nCount; ++nN )
1391     {
1392         aSingleLabel[0] <<= rDates[nN];
1393         aNewCategories.push_back(aSingleLabel);
1394     }
1395 
1396     if( m_bDataInColumns )
1397         m_aInternalData.setComplexRowLabels( aNewCategories );
1398     else
1399         m_aInternalData.setComplexColumnLabels( aNewCategories );
1400 }
1401 
1402 // ____ XAnyDescriptionAccess ____
getAnyRowDescriptions()1403 Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyRowDescriptions()
1404 {
1405     return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexRowLabels() );
1406 }
setAnyRowDescriptions(const Sequence<Sequence<uno::Any>> & aRowDescriptions)1407 void SAL_CALL InternalDataProvider::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& aRowDescriptions )
1408 {
1409     m_aInternalData.setComplexRowLabels( lcl_convertSequenceSequenceToVectorVector( aRowDescriptions ) );
1410 }
getAnyColumnDescriptions()1411 Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyColumnDescriptions()
1412 {
1413     return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexColumnLabels() );
1414 }
setAnyColumnDescriptions(const Sequence<Sequence<uno::Any>> & aColumnDescriptions)1415 void SAL_CALL InternalDataProvider::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& aColumnDescriptions )
1416 {
1417     m_aInternalData.setComplexColumnLabels( lcl_convertSequenceSequenceToVectorVector( aColumnDescriptions ) );
1418 }
1419 
1420 // ____ XComplexDescriptionAccess ____
getComplexRowDescriptions()1421 Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions()
1422 {
1423     return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexRowLabels() ));
1424 }
setComplexRowDescriptions(const Sequence<Sequence<OUString>> & aRowDescriptions)1425 void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< OUString > >& aRowDescriptions )
1426 {
1427     m_aInternalData.setComplexRowLabels( lcl_convertComplexStringSequenceToAnyVector(aRowDescriptions) );
1428 }
getComplexColumnDescriptions()1429 Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions()
1430 {
1431     return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexColumnLabels() ));
1432 }
setComplexColumnDescriptions(const Sequence<Sequence<OUString>> & aColumnDescriptions)1433 void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< OUString > >& aColumnDescriptions )
1434 {
1435     m_aInternalData.setComplexColumnLabels( lcl_convertComplexStringSequenceToAnyVector(aColumnDescriptions) );
1436 }
1437 
1438 // ____ XChartDataArray ____
getData()1439 Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData()
1440 {
1441     return m_aInternalData.getData();
1442 }
1443 
setData(const Sequence<Sequence<double>> & rDataInRows)1444 void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows )
1445 {
1446     return m_aInternalData.setData( rDataInRows );
1447 }
1448 
setRowDescriptions(const Sequence<OUString> & aRowDescriptions)1449 void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions )
1450 {
1451     vector< vector< uno::Any > > aComplexDescriptions( aRowDescriptions.getLength() );
1452     transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(),
1453                aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1454     m_aInternalData.setComplexRowLabels( aComplexDescriptions );
1455 }
1456 
setColumnDescriptions(const Sequence<OUString> & aColumnDescriptions)1457 void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
1458 {
1459     vector< vector< uno::Any > > aComplexDescriptions( aColumnDescriptions.getLength() );
1460     transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(),
1461                aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1462     m_aInternalData.setComplexColumnLabels( aComplexDescriptions );
1463 }
1464 
getRowDescriptions()1465 Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
1466 {
1467     vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexRowLabels() );
1468     SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
1469     return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
1470 }
1471 
getColumnDescriptions()1472 Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
1473 {
1474     vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexColumnLabels() );
1475     SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
1476     return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
1477 }
1478 
1479 // ____ XChartData (base of XChartDataArray) ____
addChartDataChangeEventListener(const Reference<css::chart::XChartDataChangeEventListener> &)1480 void SAL_CALL InternalDataProvider::addChartDataChangeEventListener(
1481     const Reference< css::chart::XChartDataChangeEventListener >& )
1482 {
1483 }
1484 
removeChartDataChangeEventListener(const Reference<css::chart::XChartDataChangeEventListener> &)1485 void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener(
1486     const Reference< css::chart::XChartDataChangeEventListener >& )
1487 {
1488 }
1489 
getNotANumber()1490 double SAL_CALL InternalDataProvider::getNotANumber()
1491 {
1492     double fNan;
1493     ::rtl::math::setNan( & fNan );
1494     return fNan;
1495 }
1496 
isNotANumber(double nNumber)1497 sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber )
1498 {
1499     return std::isnan( nNumber )
1500         || std::isinf( nNumber );
1501 }
1502 // lang::XInitialization:
initialize(const uno::Sequence<uno::Any> & _aArguments)1503 void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments)
1504 {
1505     comphelper::SequenceAsHashMap aArgs(_aArguments);
1506     if ( aArgs.getUnpackedValueOrDefault( "CreateDefaultData", false ) )
1507             m_aInternalData.createDefaultData();
1508 }
1509 
1510 // ____ XCloneable ____
createClone()1511 Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone()
1512 {
1513     return Reference< util::XCloneable >( new InternalDataProvider( *this ));
1514 }
1515 
getImplementationName()1516 OUString SAL_CALL InternalDataProvider::getImplementationName()
1517 {
1518     // note: in xmloff this name is used to indicate usage of own data
1519     return "com.sun.star.comp.chart.InternalDataProvider";
1520 }
1521 
supportsService(const OUString & rServiceName)1522 sal_Bool SAL_CALL InternalDataProvider::supportsService( const OUString& rServiceName )
1523 {
1524     return cppu::supportsService(this, rServiceName);
1525 }
1526 
getSupportedServiceNames()1527 css::uno::Sequence< OUString > SAL_CALL InternalDataProvider::getSupportedServiceNames()
1528 {
1529     return { "com.sun.star.chart2.data.DataProvider" };
1530 }
1531 
1532 } //  namespace chart
1533 
1534 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)1535 com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext *,
1536         css::uno::Sequence<css::uno::Any> const &)
1537 {
1538     return cppu::acquire(new ::chart::InternalDataProvider);
1539 }
1540 
1541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1542