Coverage Report

Created: 2026-03-31 11:00

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