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 "DataSourceHelper.hxx"
23 #include "DataSeriesHelper.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>
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
46 void lcl_ShowDataSource( const Reference
< data::XDataSource
> & xSource
);
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
)
69 return InterpretedData();
71 #if OSL_DEBUG_LEVEL > 1
72 lcl_ShowDataSource( xSource
);
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
));
85 bool bCategoriesUsed
= false;
86 for( sal_Int32 i
=0; i
< aData
.getLength(); ++i
)
90 if( bHasCategories
&& ! bCategoriesUsed
)
92 xCategories
.set( aData
[i
] );
94 SetRole( xCategories
->getValues(), "categories");
95 bCategoriesUsed
= true;
99 aSequencesVec
.push_back( aData
[i
] );
101 SetRole( aData
[i
]->getValues(), "values-y");
104 catch( const uno::Exception
& ex
)
106 ASSERT_EXCEPTION( ex
);
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
] );
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
);
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
;
156 Reference
< data::XLabeledDataSequence
> xValuesY(
157 DataSeriesHelper::getDataSequenceByRole( xSeriesSource
, "values-y", false ));
158 // re-use values-... as values-y
162 DataSeriesHelper::getDataSequenceByRole( xSeriesSource
, "values", true ));
164 SetRole( xValuesY
->getValues(), "values-y");
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
177 for( ; j
<aSeqs
.getLength(); ++j
)
179 OSL_ENSURE( aSeqs
[j
] == xValuesY
, "All sequences should be used" );
182 Reference
< data::XDataSink
> xSink( xSeriesSource
, uno::UNO_QUERY_THROW
);
183 xSink
->setData( aNewSequences
);
186 catch( const uno::Exception
& ex
)
188 ASSERT_EXCEPTION( ex
);
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 )
210 catch( const uno::Exception
& ex
)
212 ASSERT_EXCEPTION( ex
);
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 )
230 Reference
< data::XDataSequence
> xSeq( xLSeqToCmp
->getValues());
234 m_aValuesRangeRep
= xSeq
->getSourceRangeRepresentation();
237 xSeq
.set( xLSeqToCmp
->getLabel());
241 m_aLabelRangeRep
= xSeq
->getSourceRangeRepresentation();
246 bool operator() ( const Reference
< data::XLabeledDataSequence
> & xSeq
)
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())) )
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() +
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
)
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
);
334 void DataInterpreter::SetRole( const Reference
< data::XDataSequence
> & xSeq
, const OUString
& rRole
)
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
;
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";
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();
417 #if OSL_DEBUG_LEVEL > 1
421 void lcl_ShowDataSource( const Reference
< data::XDataSource
> & xSource
)
426 SAL_INFO("chart2", "DataSource in DataInterpreter:" );
427 Sequence
< Reference
< data::XLabeledDataSequence
> > aSequences( xSource
->getDataSequences());
428 Reference
< beans::XPropertySet
> xProp
;
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
);
440 ( xProp
->getPropertyValue( "Role") >>= aId
))
442 SAL_INFO("chart2", " <data sequence " << k
<< "> Role: " << aId
<< ", Source: "<< aSourceRepr
);
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
);
454 ( xProp
->getPropertyValue( "Role") >>= aId
))
456 SAL_INFO("chart2", " <data sequence label " << k
<< "> Role: " << aId
457 << ", Source: " << aSourceRepr
);
461 SAL_INFO("chart2", " <data sequence label " << k
<< "> unknown Role, Source: " << aSourceRepr
);
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */