update dev300-m58
[ooovba.git] / chart2 / source / model / template / DataInterpreter.cxx
blob41991068f56f4310362f64439169251ea95e18cc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataInterpreter.cxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
34 #include "DataInterpreter.hxx"
35 #include "DataSeries.hxx"
36 #include "DataSourceHelper.hxx"
37 #include "DataSeriesHelper.hxx"
38 #include "macros.hxx"
39 #include "CommonConverters.hxx"
40 #include "ContainerHelper.hxx"
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/chart2/data/XDataSink.hpp>
44 #include <vector>
45 #include <algorithm>
46 #include <iterator>
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::chart2;
50 using namespace ::std;
51 using namespace ::chart::ContainerHelper;
53 using ::com::sun::star::uno::Reference;
54 using ::com::sun::star::uno::Sequence;
55 using ::rtl::OUString;
57 #if OSL_DEBUG_LEVEL > 1
58 namespace
60 void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource );
62 #endif
64 namespace chart
67 DataInterpreter::DataInterpreter(
68 const Reference< uno::XComponentContext > & xContext ) :
69 m_xContext( xContext )
72 DataInterpreter::~DataInterpreter()
75 Reference< uno::XComponentContext > DataInterpreter::GetComponentContext() const
77 return m_xContext;
80 // ____ XDataInterpreter ____
81 InterpretedData SAL_CALL DataInterpreter::interpretDataSource(
82 const Reference< data::XDataSource >& xSource,
83 const Sequence< beans::PropertyValue >& aArguments,
84 const Sequence< Reference< XDataSeries > >& aSeriesToReUse )
85 throw (uno::RuntimeException)
87 if( ! xSource.is())
88 return InterpretedData();
90 #if OSL_DEBUG_LEVEL > 2
91 lcl_ShowDataSource( xSource );
92 #endif
94 Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() );
96 Reference< data::XLabeledDataSequence > xCategories;
97 vector< Reference< data::XLabeledDataSequence > > aSequencesVec;
99 // check if we should use categories
101 bool bHasCategories( HasCategories( aArguments, aData ));
103 // parse data
104 bool bCategoriesUsed = false;
105 for( sal_Int32 i=0; i < aData.getLength(); ++i )
109 if( bHasCategories && ! bCategoriesUsed )
111 xCategories.set( aData[i] );
112 if( xCategories.is())
113 SetRole( xCategories->getValues(), C2U("categories"));
114 bCategoriesUsed = true;
116 else
118 aSequencesVec.push_back( aData[i] );
119 if( aData[i].is())
120 SetRole( aData[i]->getValues(), C2U("values-y"));
123 catch( uno::Exception & ex )
125 ASSERT_EXCEPTION( ex );
129 // create DataSeries
130 vector< Reference< data::XLabeledDataSequence > >::const_iterator
131 aSequencesVecIt = aSequencesVec.begin();
133 sal_Int32 nSeriesIndex = 0;
134 vector< Reference< XDataSeries > > aSeriesVec;
135 aSeriesVec.reserve( aSequencesVec.size());
137 for( ;aSequencesVecIt != aSequencesVec.end(); ++aSequencesVecIt, ++nSeriesIndex )
139 Sequence< Reference< data::XLabeledDataSequence > > aNewData( & (*aSequencesVecIt), 1 );
140 Reference< XDataSeries > xSeries;
141 if( nSeriesIndex < aSeriesToReUse.getLength())
142 xSeries.set( aSeriesToReUse[nSeriesIndex] );
143 else
144 xSeries.set( new DataSeries( GetComponentContext() ));
145 OSL_ASSERT( xSeries.is() );
146 Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY );
147 OSL_ASSERT( xSink.is() );
148 xSink->setData( aNewData );
150 aSeriesVec.push_back( xSeries );
153 Sequence< Sequence< Reference< XDataSeries > > > aSeries(1);
154 aSeries[0] = ContainerToSequence( aSeriesVec );
155 return InterpretedData( aSeries, xCategories, Sequence< Reference< data::XLabeledDataSequence > >() );
158 InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries(
159 const InterpretedData& aInterpretedData )
160 throw (uno::RuntimeException)
162 InterpretedData aResult( aInterpretedData );
163 vector< Reference< data::XLabeledDataSequence > > aUnused(
164 SequenceToVector( aInterpretedData.UnusedData ));
166 sal_Int32 i=0;
167 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
168 const sal_Int32 nCount = aSeries.getLength();
169 for( ; i<nCount; ++i )
173 Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW );
174 Sequence< Reference< data::XLabeledDataSequence > > aNewSequences;
176 // values-y
177 Reference< data::XLabeledDataSequence > xValuesY(
178 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false ));
179 // re-use values-... as values-y
180 if( ! xValuesY.is())
182 xValuesY.set(
183 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values"), true ));
184 if( xValuesY.is())
185 SetRole( xValuesY->getValues(), C2U("values-y"));
187 if( xValuesY.is())
189 aNewSequences.realloc(1);
190 aNewSequences[0] = xValuesY;
193 Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences());
194 if( aSeqs.getLength() != aNewSequences.getLength() )
196 sal_Int32 j=0;
197 for( ; j<aSeqs.getLength(); ++j )
199 if( aSeqs[j] != xValuesY )
200 aUnused.push_back( aSeqs[j] );
202 Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW );
204 xSink->setData( aNewSequences );
207 catch( uno::Exception & ex )
209 ASSERT_EXCEPTION( ex );
213 aResult.UnusedData = ContainerToSequence( aUnused );
215 return aResult;
218 // criterion: all series must have exactly one data::XLabeledDataSequence
219 sal_Bool SAL_CALL DataInterpreter::isDataCompatible(
220 const chart2::InterpretedData& aInterpretedData )
221 throw (uno::RuntimeException)
223 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
224 for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
228 Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW );
229 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
230 if( aSeq.getLength() != 1 )
231 return sal_False;
233 catch( uno::Exception & ex )
235 ASSERT_EXCEPTION( ex );
239 return sal_True;
242 namespace
245 struct lcl_LabeledSequenceEquals : public unary_function< Reference< data::XLabeledDataSequence >, bool >
247 lcl_LabeledSequenceEquals( const Reference< data::XLabeledDataSequence > & xLSeqToCmp ) :
248 m_bHasLabels ( false ),
249 m_bHasValues ( false )
251 if( xLSeqToCmp.is())
253 Reference< data::XDataSequence > xSeq( xLSeqToCmp->getValues());
254 if( xSeq.is())
256 m_bHasValues = true;
257 m_aValuesRangeRep = xSeq->getSourceRangeRepresentation();
260 xSeq.set( xLSeqToCmp->getLabel());
261 if( xSeq.is())
263 m_bHasLabels = true;
264 m_aLabelRangeRep = xSeq->getSourceRangeRepresentation();
269 bool operator() ( const Reference< data::XLabeledDataSequence > & xSeq )
271 if( ! xSeq.is())
272 return false;
274 Reference< data::XDataSequence > xSeqValues( xSeq->getValues() );
275 Reference< data::XDataSequence > xSeqLabels( xSeq->getLabel() );
276 bool bHasValues = xSeqValues.is();
277 bool bHasLabels = xSeqLabels.is();
279 return ( ( (m_bHasValues == bHasValues) &&
280 (!bHasValues || m_aValuesRangeRep.equals( xSeqValues->getSourceRangeRepresentation())) ) &&
281 ( (m_bHasLabels == bHasLabels) &&
282 (!bHasLabels || m_aLabelRangeRep.equals( xSeqLabels->getSourceRangeRepresentation())) )
286 private:
287 bool m_bHasLabels;
288 bool m_bHasValues;
289 OUString m_aValuesRangeRep;
290 OUString m_aLabelRangeRep;
293 } // anonymous namespace
295 Reference< data::XDataSource > SAL_CALL DataInterpreter::mergeInterpretedData(
296 const InterpretedData& aInterpretedData )
297 throw (uno::RuntimeException)
299 vector< Reference< data::XLabeledDataSequence > > aResultVec;
300 vector< Reference< data::XLabeledDataSequence > > aUnusedDataVec;
301 aResultVec.reserve( aInterpretedData.Series.getLength() +
302 aInterpretedData.UnusedData.getLength() +
303 1 // categories
306 if( aInterpretedData.Categories.is())
307 aResultVec.push_back( aInterpretedData.Categories );
309 // add unused data that has the Role categories at front
310 if( aInterpretedData.UnusedData.getLength())
312 sal_Int32 nSize = aInterpretedData.UnusedData.getLength();
313 for( sal_Int32 i=0; i<nSize; ++i )
315 Reference< data::XLabeledDataSequence > xPotentialCategories( aInterpretedData.UnusedData[i] );
316 if( xPotentialCategories.is() )
318 if( GetRole( xPotentialCategories->getValues()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("categories")))
319 aResultVec.push_back( xPotentialCategories );
320 else
321 aUnusedDataVec.push_back( xPotentialCategories );
325 else
326 aUnusedDataVec = SequenceToVector( aInterpretedData.UnusedData );
328 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
329 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
333 Reference< data::XDataSource > xSrc( aSeries[nSeriesIdx], uno::UNO_QUERY_THROW );
334 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
336 // add all sequences of data series
337 for( sal_Int32 nSeqIdx=0; nSeqIdx<aSeq.getLength(); ++nSeqIdx )
339 Reference< data::XLabeledDataSequence > xAdd( aSeq[nSeqIdx] );
341 // only add if sequence is not yet in the result
342 if( find_if( aResultVec.begin(), aResultVec.end(),
343 lcl_LabeledSequenceEquals( xAdd )) == aResultVec.end())
345 aResultVec.push_back( xAdd );
349 catch( uno::Exception & ex )
351 ASSERT_EXCEPTION( ex );
355 // add unused data at end
356 copy( aUnusedDataVec.begin(), aUnusedDataVec.end(), back_inserter( aResultVec ));
358 return Reference< data::XDataSource >( DataSourceHelper::createDataSource( ContainerToSequence( aResultVec ) ) );
361 // convenience methods
363 // static
364 OUString DataInterpreter::GetRole( const Reference< data::XDataSequence > & xSeq )
366 OUString aResult;
367 if( ! xSeq.is())
368 return aResult;
372 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
373 xProp->getPropertyValue( C2U("Role")) >>= aResult;
375 catch( uno::Exception & ex )
377 ASSERT_EXCEPTION( ex );
379 return aResult;
382 // static
383 void DataInterpreter::SetRole( const Reference< data::XDataSequence > & xSeq, const OUString & rRole )
385 if( ! xSeq.is())
386 return;
389 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
390 xProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
392 catch( uno::Exception & ex )
394 ASSERT_EXCEPTION( ex );
398 // static
399 uno::Any DataInterpreter::GetProperty(
400 const Sequence< beans::PropertyValue > & aArguments,
401 const OUString & rName )
403 for( sal_Int32 i=aArguments.getLength(); i--; )
405 if( aArguments[i].Name.equals( rName ))
406 return aArguments[i].Value;
408 return uno::Any();
411 // static
412 bool DataInterpreter::HasCategories(
413 const Sequence< beans::PropertyValue > & rArguments,
414 const Sequence< Reference< data::XLabeledDataSequence > > & rData )
416 bool bHasCategories = false;
418 if( rArguments.getLength() > 0 )
419 GetProperty( rArguments, C2U(("HasCategories"))) >>= bHasCategories;
421 for( sal_Int32 nLSeqIdx=0; ! bHasCategories && nLSeqIdx<rData.getLength(); ++nLSeqIdx )
422 bHasCategories = ( rData[nLSeqIdx].is() &&
423 GetRole( rData[nLSeqIdx]->getValues()).equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")));
425 return bHasCategories;
428 // ------------------------------------------------------------
430 Sequence< OUString > DataInterpreter::getSupportedServiceNames_Static()
432 Sequence< OUString > aServices( 1 );
433 aServices[0] = C2U( "com.sun.star.chart2.DataInterpreter" );
434 return aServices;
437 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
438 APPHELPER_XSERVICEINFO_IMPL( DataInterpreter, C2U("com.sun.star.comp.chart2.DataInterpreter"));
440 } // namespace chart
442 #if OSL_DEBUG_LEVEL > 1
443 namespace
446 void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource )
448 if( ! xSource.is())
449 return;
451 OSL_TRACE( "DataSource in DataInterpreter:" );
452 Sequence< Reference< data::XLabeledDataSequence > > aSequences( xSource->getDataSequences());
453 Reference< beans::XPropertySet > xProp;
454 OUString aId;
455 const sal_Int32 nMax = aSequences.getLength();
456 for( sal_Int32 k = 0; k < nMax; ++k )
458 if( aSequences[k].is())
460 OUString aSourceRepr(C2U("<none>"));
461 if( aSequences[k]->getValues().is())
462 aSourceRepr = aSequences[k]->getValues()->getSourceRangeRepresentation();
463 xProp.set( aSequences[k]->getValues(), uno::UNO_QUERY );
464 if( xProp.is() &&
465 ( xProp->getPropertyValue( C2U( "Role" )) >>= aId ))
467 OSL_TRACE( " <data sequence %d> Role: %s, Source: %s", k, U2C( aId ), U2C( aSourceRepr ));
469 else
471 OSL_TRACE( " <data sequence %d> unknown Role, Source: %s", k, U2C( aSourceRepr ) );
474 aSourceRepr = C2U("<none>");
475 if( aSequences[k]->getLabel().is())
476 aSourceRepr = OUString( aSequences[k]->getLabel()->getSourceRangeRepresentation());
477 xProp.set( aSequences[k]->getLabel(), uno::UNO_QUERY );
478 if( xProp.is() &&
479 ( xProp->getPropertyValue( C2U( "Role" )) >>= aId ))
481 OSL_TRACE( " <data sequence label %d> Role: %s, Source: %s", k, U2C( aId ), U2C( aSourceRepr ));
483 else
485 OSL_TRACE( " <data sequence label %d> unknown Role, Source: %s", k, U2C( aSourceRepr ) );
492 #endif