Coverage Report

Created: 2025-07-07 10:01

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