1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <DataInterpreter.hxx>
21 #include <DataSeries.hxx>
22 #include <DataSource.hxx>
23 #include <DataSeriesHelper.hxx>
24 #include <CommonConverters.hxx>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <comphelper/diagnose_ex.hxx>
32 using namespace ::com::sun::star
;
33 using namespace ::com::sun::star::chart2
;
35 using ::com::sun::star::uno::Reference
;
36 using ::com::sun::star::uno::Sequence
;
38 #ifdef DEBUG_CHART2_TEMPLATE
41 void lcl_ShowDataSource( const Reference
< data::XDataSource
> & xSource
);
48 DataInterpreter::DataInterpreter()
51 DataInterpreter::~DataInterpreter()
54 // ____ XDataInterpreter ____
55 InterpretedData
DataInterpreter::interpretDataSource(
56 const Reference
< data::XDataSource
>& xSource
,
57 const Sequence
< beans::PropertyValue
>& aArguments
,
58 const std::vector
< rtl::Reference
< DataSeries
> >& aSeriesToReUse
)
61 return InterpretedData();
63 #ifdef DEBUG_CHART2_TEMPLATE
64 lcl_ShowDataSource( xSource
);
67 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aData
= getDataSequences(xSource
);
69 uno::Reference
< chart2::data::XLabeledDataSequence
> xCategories
;
70 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aSequencesVec
;
72 // check if we should use categories
74 bool bHasCategories( HasCategories( aArguments
, aData
));
77 bool bCategoriesUsed
= false;
78 for( uno::Reference
< chart2::data::XLabeledDataSequence
> const & labeledData
: aData
)
82 if( bHasCategories
&& ! bCategoriesUsed
)
84 xCategories
= labeledData
;
86 SetRole( xCategories
->getValues(), u
"categories"_ustr
);
87 bCategoriesUsed
= true;
91 aSequencesVec
.push_back( labeledData
);
93 SetRole( labeledData
->getValues(), u
"values-y"_ustr
);
96 catch( const uno::Exception
& )
98 DBG_UNHANDLED_EXCEPTION("chart2");
103 std::size_t nSeriesIndex
= 0;
104 std::vector
< rtl::Reference
< DataSeries
> > aSeriesVec
;
105 aSeriesVec
.reserve( aSequencesVec
.size());
107 for (auto const& elem
: aSequencesVec
)
109 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aNewData
{ elem
};
110 rtl::Reference
< DataSeries
> xSeries
;
111 if( nSeriesIndex
< aSeriesToReUse
.size())
112 xSeries
= aSeriesToReUse
[nSeriesIndex
];
114 xSeries
= new DataSeries
;
115 assert( xSeries
.is() );
116 xSeries
->setData( aNewData
);
118 aSeriesVec
.push_back( xSeries
);
122 return { { std::move(aSeriesVec
) }, xCategories
};
125 InterpretedData
DataInterpreter::reinterpretDataSeries(
126 const InterpretedData
& aInterpretedData
)
128 InterpretedData
aResult( aInterpretedData
);
131 std::vector
< rtl::Reference
< DataSeries
> > aSeries( FlattenSequence( aInterpretedData
.Series
));
132 const sal_Int32 nCount
= aSeries
.size();
133 for( ; i
<nCount
; ++i
)
137 std::vector
< uno::Reference
< data::XLabeledDataSequence
> > aNewSequences
;
140 uno::Reference
< data::XLabeledDataSequence
> xValuesY
=
141 DataSeriesHelper::getDataSequenceByRole( aSeries
[i
], u
"values-y"_ustr
);
142 // re-use values-... as values-y
146 DataSeriesHelper::getDataSequenceByRole( aSeries
[i
], u
"values"_ustr
, true );
148 SetRole( xValuesY
->getValues(), u
"values-y"_ustr
);
152 aNewSequences
= { xValuesY
};
155 const std::vector
< uno::Reference
< data::XLabeledDataSequence
> > & aSeqs
= aSeries
[i
]->getDataSequences2();
156 if( aSeqs
.size() != aNewSequences
.size() )
158 #ifdef DEBUG_CHART2_TEMPLATE
160 for( ; j
<aSeqs
.(); ++j
)
162 assert( aSeqs
[j
] == xValuesY
&& "All sequences should be used" );
165 aSeries
[i
]->setData( aNewSequences
);
168 catch( const uno::Exception
& )
170 DBG_UNHANDLED_EXCEPTION("chart2");
177 // criterion: all series must have exactly one data::XLabeledDataSequence
178 bool DataInterpreter::isDataCompatible(
179 const InterpretedData
& aInterpretedData
)
181 const std::vector
< rtl::Reference
< DataSeries
> > aSeries( FlattenSequence( aInterpretedData
.Series
));
182 for( rtl::Reference
< DataSeries
> const & i
: aSeries
)
186 if( i
->getDataSequences2().size() != 1 )
189 catch( const uno::Exception
& )
191 DBG_UNHANDLED_EXCEPTION("chart2");
201 struct lcl_LabeledSequenceEquals
203 explicit lcl_LabeledSequenceEquals( const Reference
< data::XLabeledDataSequence
> & xLSeqToCmp
) :
204 m_bHasLabels ( false ),
205 m_bHasValues ( false )
207 if( !xLSeqToCmp
.is())
210 Reference
< data::XDataSequence
> xSeq( xLSeqToCmp
->getValues());
214 m_aValuesRangeRep
= xSeq
->getSourceRangeRepresentation();
217 xSeq
.set( xLSeqToCmp
->getLabel());
221 m_aLabelRangeRep
= xSeq
->getSourceRangeRepresentation();
225 bool operator() ( const Reference
< data::XLabeledDataSequence
> & xSeq
)
230 Reference
< data::XDataSequence
> xSeqValues( xSeq
->getValues() );
231 Reference
< data::XDataSequence
> xSeqLabels( xSeq
->getLabel() );
232 bool bHasValues
= xSeqValues
.is();
233 bool bHasLabels
= xSeqLabels
.is();
235 return ( ( (m_bHasValues
== bHasValues
) &&
236 (!bHasValues
|| m_aValuesRangeRep
== xSeqValues
->getSourceRangeRepresentation()) ) &&
237 ( (m_bHasLabels
== bHasLabels
) &&
238 (!bHasLabels
|| m_aLabelRangeRep
== xSeqLabels
->getSourceRangeRepresentation()) )
245 OUString m_aValuesRangeRep
;
246 OUString m_aLabelRangeRep
;
249 } // anonymous namespace
251 rtl::Reference
< DataSource
> DataInterpreter::mergeInterpretedData(
252 const InterpretedData
& aInterpretedData
)
254 std::vector
< Reference
< data::XLabeledDataSequence
> > aResultVec
;
255 aResultVec
.reserve( aInterpretedData
.Series
.size() +
259 if( aInterpretedData
.Categories
.is())
260 aResultVec
.push_back( aInterpretedData
.Categories
);
262 const std::vector
< rtl::Reference
< DataSeries
> > aSeries
= FlattenSequence( aInterpretedData
.Series
);
263 for( rtl::Reference
< DataSeries
> const & dataSeries
: aSeries
)
267 // add all sequences of data series
268 for( uno::Reference
< data::XLabeledDataSequence
> const & xAdd
: dataSeries
->getDataSequences2() )
270 // only add if sequence is not yet in the result
271 if( none_of( aResultVec
.begin(), aResultVec
.end(),
272 lcl_LabeledSequenceEquals( xAdd
)) )
274 aResultVec
.push_back( xAdd
);
278 catch( const uno::Exception
& )
280 DBG_UNHANDLED_EXCEPTION("chart2");
284 return new DataSource(aResultVec
);
287 uno::Any
DataInterpreter::getChartTypeSpecificData(
293 // convenience methods
295 OUString
DataInterpreter::GetRole( const Reference
< data::XDataSequence
> & xSeq
)
303 Reference
< beans::XPropertySet
> xProp( xSeq
, uno::UNO_QUERY_THROW
);
304 xProp
->getPropertyValue( u
"Role"_ustr
) >>= aResult
;
306 catch( const uno::Exception
& )
308 DBG_UNHANDLED_EXCEPTION("chart2");
313 void DataInterpreter::SetRole( const Reference
< data::XDataSequence
> & xSeq
, const OUString
& rRole
)
319 Reference
< beans::XPropertySet
> xProp( xSeq
, uno::UNO_QUERY_THROW
);
320 xProp
->setPropertyValue( u
"Role"_ustr
, uno::Any( rRole
));
322 catch( const uno::Exception
& )
324 DBG_UNHANDLED_EXCEPTION("chart2");
328 uno::Any
DataInterpreter::GetProperty(
329 const Sequence
< beans::PropertyValue
> & aArguments
,
330 std::u16string_view rName
)
332 for( sal_Int32 i
=aArguments
.getLength(); i
--; )
334 if( aArguments
[i
].Name
== rName
)
335 return aArguments
[i
].Value
;
340 bool DataInterpreter::HasCategories(
341 const Sequence
< beans::PropertyValue
> & rArguments
,
342 const std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > & rData
)
344 bool bHasCategories
= false;
346 if( rArguments
.hasElements() )
347 GetProperty( rArguments
, u
"HasCategories" ) >>= bHasCategories
;
349 for( std::size_t nLSeqIdx
=0; ! bHasCategories
&& nLSeqIdx
<rData
.size(); ++nLSeqIdx
)
350 bHasCategories
= ( rData
[nLSeqIdx
].is() && GetRole( rData
[nLSeqIdx
]->getValues() ) == "categories");
352 return bHasCategories
;
355 bool DataInterpreter::UseCategoriesAsX( const Sequence
< beans::PropertyValue
> & rArguments
)
357 bool bUseCategoriesAsX
= true;
358 if( rArguments
.hasElements() )
359 GetProperty( rArguments
, u
"UseCategoriesAsX" ) >>= bUseCategoriesAsX
;
360 return bUseCategoriesAsX
;
363 OUString SAL_CALL
DataInterpreter::getImplementationName()
365 return u
"com.sun.star.comp.chart2.DataInterpreter"_ustr
;
368 sal_Bool SAL_CALL
DataInterpreter::supportsService( const OUString
& rServiceName
)
370 return cppu::supportsService(this, rServiceName
);
373 css::uno::Sequence
< OUString
> SAL_CALL
DataInterpreter::getSupportedServiceNames()
375 return { u
"com.sun.star.chart2.DataInterpreter"_ustr
};
378 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > DataInterpreter::getDataSequences(
379 const css::uno::Reference
< css::chart2::data::XDataSource
>& xSource
)
381 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aData
;
382 for (const Reference
< data::XLabeledDataSequence
> & rLDS
: xSource
->getDataSequences() )
384 aData
.push_back(rLDS
);
391 #ifdef DEBUG_CHART2_TEMPLATE
395 void lcl_ShowDataSource( const Reference
< data::XDataSource
> & xSource
)
400 SAL_INFO("chart2", "DataSource in DataInterpreter:" );
401 Sequence
< Reference
< data::XLabeledDataSequence
> > aSequences( xSource
->getDataSequences());
402 Reference
< beans::XPropertySet
> xProp
;
404 const sal_Int32 nMax
= aSequences
.getLength();
405 for( sal_Int32 k
= 0; k
< nMax
; ++k
)
407 if( aSequences
[k
].is())
409 OUString
aSourceRepr("<none>");
410 if( aSequences
[k
]->getValues().is())
411 aSourceRepr
= aSequences
[k
]->getValues()->getSourceRangeRepresentation();
412 xProp
.set( aSequences
[k
]->getValues(), uno::UNO_QUERY
);
414 ( xProp
->getPropertyValue( "Role") >>= aId
))
416 SAL_INFO("chart2", " <data sequence " << k
<< "> Role: " << aId
<< ", Source: "<< aSourceRepr
);
420 SAL_INFO("chart2", " <data sequence " << k
<< "> unknown Role, Source: " << aSourceRepr
);
423 aSourceRepr
= "<none>";
424 if( aSequences
[k
]->getLabel().is())
425 aSourceRepr
= aSequences
[k
]->getLabel()->getSourceRangeRepresentation();
426 xProp
.set( aSequences
[k
]->getLabel(), uno::UNO_QUERY
);
428 ( xProp
->getPropertyValue( "Role") >>= aId
))
430 SAL_INFO("chart2", " <data sequence label " << k
<< "> Role: " << aId
431 << ", Source: " << aSourceRepr
);
435 SAL_INFO("chart2", " <data sequence label " << k
<< "> unknown Role, Source: " << aSourceRepr
);
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */