fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / model / template / DataInterpreter.cxx
blob5db7d665534464305ec6cd50a58f758d8aedbd7b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "DataSourceHelper.hxx"
23 #include "DataSeriesHelper.hxx"
24 #include "macros.hxx"
25 #include "CommonConverters.hxx"
26 #include "ContainerHelper.hxx"
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/chart2/data/XDataSink.hpp>
29 #include <cppuhelper/supportsservice.hxx>
31 #include <vector>
32 #include <algorithm>
33 #include <iterator>
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::chart2;
37 using namespace ::std;
38 using namespace ::chart::ContainerHelper;
40 using ::com::sun::star::uno::Reference;
41 using ::com::sun::star::uno::Sequence;
43 #if OSL_DEBUG_LEVEL > 1
44 namespace
46 void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource );
48 #endif
50 namespace chart
53 DataInterpreter::DataInterpreter(
54 const Reference< uno::XComponentContext > & xContext ) :
55 m_xContext( xContext )
58 DataInterpreter::~DataInterpreter()
61 // ____ XDataInterpreter ____
62 InterpretedData SAL_CALL DataInterpreter::interpretDataSource(
63 const Reference< data::XDataSource >& xSource,
64 const Sequence< beans::PropertyValue >& aArguments,
65 const Sequence< Reference< XDataSeries > >& aSeriesToReUse )
66 throw (uno::RuntimeException, std::exception)
68 if( ! xSource.is())
69 return InterpretedData();
71 #if OSL_DEBUG_LEVEL > 1
72 lcl_ShowDataSource( xSource );
73 #endif
75 Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() );
77 Reference< data::XLabeledDataSequence > xCategories;
78 vector< Reference< data::XLabeledDataSequence > > aSequencesVec;
80 // check if we should use categories
82 bool bHasCategories( HasCategories( aArguments, aData ));
84 // parse data
85 bool bCategoriesUsed = false;
86 for( sal_Int32 i=0; i < aData.getLength(); ++i )
88 try
90 if( bHasCategories && ! bCategoriesUsed )
92 xCategories.set( aData[i] );
93 if( xCategories.is())
94 SetRole( xCategories->getValues(), "categories");
95 bCategoriesUsed = true;
97 else
99 aSequencesVec.push_back( aData[i] );
100 if( aData[i].is())
101 SetRole( aData[i]->getValues(), "values-y");
104 catch( const uno::Exception & ex )
106 ASSERT_EXCEPTION( ex );
110 // create DataSeries
111 vector< Reference< data::XLabeledDataSequence > >::const_iterator
112 aSequencesVecIt = aSequencesVec.begin();
114 sal_Int32 nSeriesIndex = 0;
115 vector< Reference< XDataSeries > > aSeriesVec;
116 aSeriesVec.reserve( aSequencesVec.size());
118 for( ;aSequencesVecIt != aSequencesVec.end(); ++aSequencesVecIt, ++nSeriesIndex )
120 Sequence< Reference< data::XLabeledDataSequence > > aNewData( & (*aSequencesVecIt), 1 );
121 Reference< XDataSeries > xSeries;
122 if( nSeriesIndex < aSeriesToReUse.getLength())
123 xSeries.set( aSeriesToReUse[nSeriesIndex] );
124 else
125 xSeries.set( new DataSeries( GetComponentContext() ));
126 OSL_ASSERT( xSeries.is() );
127 Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY );
128 OSL_ASSERT( xSink.is() );
129 xSink->setData( aNewData );
131 aSeriesVec.push_back( xSeries );
134 Sequence< Sequence< Reference< XDataSeries > > > aSeries(1);
135 aSeries[0] = ContainerToSequence( aSeriesVec );
136 return InterpretedData( aSeries, xCategories );
139 InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries(
140 const InterpretedData& aInterpretedData )
141 throw (uno::RuntimeException, std::exception)
143 InterpretedData aResult( aInterpretedData );
145 sal_Int32 i=0;
146 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
147 const sal_Int32 nCount = aSeries.getLength();
148 for( ; i<nCount; ++i )
152 Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW );
153 Sequence< Reference< data::XLabeledDataSequence > > aNewSequences;
155 // values-y
156 Reference< data::XLabeledDataSequence > xValuesY(
157 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-y", false ));
158 // re-use values-... as values-y
159 if( ! xValuesY.is())
161 xValuesY.set(
162 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values", true ));
163 if( xValuesY.is())
164 SetRole( xValuesY->getValues(), "values-y");
166 if( xValuesY.is())
168 aNewSequences.realloc(1);
169 aNewSequences[0] = xValuesY;
172 Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences());
173 if( aSeqs.getLength() != aNewSequences.getLength() )
175 #if OSL_DEBUG_LEVEL > 1
176 sal_Int32 j=0;
177 for( ; j<aSeqs.getLength(); ++j )
179 OSL_ENSURE( aSeqs[j] == xValuesY, "All sequences should be used" );
181 #endif
182 Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW );
183 xSink->setData( aNewSequences );
186 catch( const uno::Exception & ex )
188 ASSERT_EXCEPTION( ex );
192 return aResult;
195 // criterion: all series must have exactly one data::XLabeledDataSequence
196 sal_Bool SAL_CALL DataInterpreter::isDataCompatible(
197 const chart2::InterpretedData& aInterpretedData )
198 throw (uno::RuntimeException, std::exception)
200 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
201 for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
205 Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW );
206 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
207 if( aSeq.getLength() != 1 )
208 return sal_False;
210 catch( const uno::Exception & ex )
212 ASSERT_EXCEPTION( ex );
216 return sal_True;
219 namespace
222 struct lcl_LabeledSequenceEquals : public std::unary_function< Reference< data::XLabeledDataSequence >, bool >
224 lcl_LabeledSequenceEquals( const Reference< data::XLabeledDataSequence > & xLSeqToCmp ) :
225 m_bHasLabels ( false ),
226 m_bHasValues ( false )
228 if( xLSeqToCmp.is())
230 Reference< data::XDataSequence > xSeq( xLSeqToCmp->getValues());
231 if( xSeq.is())
233 m_bHasValues = true;
234 m_aValuesRangeRep = xSeq->getSourceRangeRepresentation();
237 xSeq.set( xLSeqToCmp->getLabel());
238 if( xSeq.is())
240 m_bHasLabels = true;
241 m_aLabelRangeRep = xSeq->getSourceRangeRepresentation();
246 bool operator() ( const Reference< data::XLabeledDataSequence > & xSeq )
248 if( ! xSeq.is())
249 return false;
251 Reference< data::XDataSequence > xSeqValues( xSeq->getValues() );
252 Reference< data::XDataSequence > xSeqLabels( xSeq->getLabel() );
253 bool bHasValues = xSeqValues.is();
254 bool bHasLabels = xSeqLabels.is();
256 return ( ( (m_bHasValues == bHasValues) &&
257 (!bHasValues || m_aValuesRangeRep.equals( xSeqValues->getSourceRangeRepresentation())) ) &&
258 ( (m_bHasLabels == bHasLabels) &&
259 (!bHasLabels || m_aLabelRangeRep.equals( xSeqLabels->getSourceRangeRepresentation())) )
263 private:
264 bool m_bHasLabels;
265 bool m_bHasValues;
266 OUString m_aValuesRangeRep;
267 OUString m_aLabelRangeRep;
270 } // anonymous namespace
272 Reference< data::XDataSource > SAL_CALL DataInterpreter::mergeInterpretedData(
273 const InterpretedData& aInterpretedData )
274 throw (uno::RuntimeException, std::exception)
276 vector< Reference< data::XLabeledDataSequence > > aResultVec;
277 aResultVec.reserve( aInterpretedData.Series.getLength() +
278 1 // categories
281 if( aInterpretedData.Categories.is())
282 aResultVec.push_back( aInterpretedData.Categories );
284 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
285 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
289 Reference< data::XDataSource > xSrc( aSeries[nSeriesIdx], uno::UNO_QUERY_THROW );
290 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
292 // add all sequences of data series
293 for( sal_Int32 nSeqIdx=0; nSeqIdx<aSeq.getLength(); ++nSeqIdx )
295 Reference< data::XLabeledDataSequence > xAdd( aSeq[nSeqIdx] );
297 // only add if sequence is not yet in the result
298 if( find_if( aResultVec.begin(), aResultVec.end(),
299 lcl_LabeledSequenceEquals( xAdd )) == aResultVec.end())
301 aResultVec.push_back( xAdd );
305 catch( const uno::Exception & ex )
307 ASSERT_EXCEPTION( ex );
311 return Reference< data::XDataSource >( DataSourceHelper::createDataSource( ContainerToSequence( aResultVec ) ) );
314 // convenience methods
316 OUString DataInterpreter::GetRole( const Reference< data::XDataSequence > & xSeq )
318 OUString aResult;
319 if( ! xSeq.is())
320 return aResult;
324 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
325 xProp->getPropertyValue( "Role") >>= aResult;
327 catch( const uno::Exception & ex )
329 ASSERT_EXCEPTION( ex );
331 return aResult;
334 void DataInterpreter::SetRole( const Reference< data::XDataSequence > & xSeq, const OUString & rRole )
336 if( ! xSeq.is())
337 return;
340 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
341 xProp->setPropertyValue( "Role", uno::makeAny( rRole ));
343 catch( const uno::Exception & ex )
345 ASSERT_EXCEPTION( ex );
349 uno::Any DataInterpreter::GetProperty(
350 const Sequence< beans::PropertyValue > & aArguments,
351 const OUString & rName )
353 for( sal_Int32 i=aArguments.getLength(); i--; )
355 if( aArguments[i].Name.equals( rName ))
356 return aArguments[i].Value;
358 return uno::Any();
361 bool DataInterpreter::HasCategories(
362 const Sequence< beans::PropertyValue > & rArguments,
363 const Sequence< Reference< data::XLabeledDataSequence > > & rData )
365 bool bHasCategories = false;
367 if( rArguments.getLength() > 0 )
368 GetProperty( rArguments, "HasCategories" ) >>= bHasCategories;
370 for( sal_Int32 nLSeqIdx=0; ! bHasCategories && nLSeqIdx<rData.getLength(); ++nLSeqIdx )
371 bHasCategories = ( rData[nLSeqIdx].is() && GetRole( rData[nLSeqIdx]->getValues() ) == "categories");
373 return bHasCategories;
376 bool DataInterpreter::UseCategoriesAsX( const Sequence< beans::PropertyValue > & rArguments )
378 bool bUseCategoriesAsX = true;
379 if( rArguments.getLength() > 0 )
380 GetProperty( rArguments, "UseCategoriesAsX" ) >>= bUseCategoriesAsX;
381 return bUseCategoriesAsX;
384 Sequence< OUString > DataInterpreter::getSupportedServiceNames_Static()
386 Sequence< OUString > aServices( 1 );
387 aServices[0] = "com.sun.star.chart2.DataInterpreter";
388 return aServices;
391 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
392 OUString SAL_CALL DataInterpreter::getImplementationName()
393 throw( css::uno::RuntimeException, std::exception )
395 return getImplementationName_Static();
398 OUString DataInterpreter::getImplementationName_Static()
400 return OUString("com.sun.star.comp.chart2.DataInterpreter");
403 sal_Bool SAL_CALL DataInterpreter::supportsService( const OUString& rServiceName )
404 throw( css::uno::RuntimeException, std::exception )
406 return cppu::supportsService(this, rServiceName);
409 css::uno::Sequence< OUString > SAL_CALL DataInterpreter::getSupportedServiceNames()
410 throw( css::uno::RuntimeException, std::exception )
412 return getSupportedServiceNames_Static();
415 } // namespace chart
417 #if OSL_DEBUG_LEVEL > 1
418 namespace
421 void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource )
423 if( ! xSource.is())
424 return;
426 SAL_INFO("chart2", "DataSource in DataInterpreter:" );
427 Sequence< Reference< data::XLabeledDataSequence > > aSequences( xSource->getDataSequences());
428 Reference< beans::XPropertySet > xProp;
429 OUString aId;
430 const sal_Int32 nMax = aSequences.getLength();
431 for( sal_Int32 k = 0; k < nMax; ++k )
433 if( aSequences[k].is())
435 OUString aSourceRepr("<none>");
436 if( aSequences[k]->getValues().is())
437 aSourceRepr = aSequences[k]->getValues()->getSourceRangeRepresentation();
438 xProp.set( aSequences[k]->getValues(), uno::UNO_QUERY );
439 if( xProp.is() &&
440 ( xProp->getPropertyValue( "Role") >>= aId ))
442 SAL_INFO("chart2", " <data sequence " << k << "> Role: " << aId << ", Source: "<< aSourceRepr);
444 else
446 SAL_INFO("chart2", " <data sequence " << k << "> unknown Role, Source: " << aSourceRepr );
449 aSourceRepr = "<none>";
450 if( aSequences[k]->getLabel().is())
451 aSourceRepr = OUString( aSequences[k]->getLabel()->getSourceRangeRepresentation());
452 xProp.set( aSequences[k]->getLabel(), uno::UNO_QUERY );
453 if( xProp.is() &&
454 ( xProp->getPropertyValue( "Role") >>= aId ))
456 SAL_INFO("chart2", " <data sequence label " << k << "> Role: " << aId
457 << ", Source: " << aSourceRepr );
459 else
461 SAL_INFO("chart2", " <data sequence label " << k << "> unknown Role, Source: " << aSourceRepr );
468 #endif
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */