LCOV - code coverage report
Current view: top level - libreoffice/chart2/source/model/template - DataInterpreter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 54 152 35.5 %
Date: 2012-12-27 Functions: 8 22 36.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      21             : #include "DataInterpreter.hxx"
      22             : #include "DataSeries.hxx"
      23             : #include "DataSourceHelper.hxx"
      24             : #include "DataSeriesHelper.hxx"
      25             : #include "macros.hxx"
      26             : #include "CommonConverters.hxx"
      27             : #include "ContainerHelper.hxx"
      28             : #include <com/sun/star/beans/XPropertySet.hpp>
      29             : #include <com/sun/star/chart2/data/XDataSink.hpp>
      30             : 
      31             : #include <vector>
      32             : #include <algorithm>
      33             : #include <iterator>
      34             : 
      35             : using namespace ::com::sun::star;
      36             : using namespace ::com::sun::star::chart2;
      37             : using namespace ::std;
      38             : using namespace ::chart::ContainerHelper;
      39             : 
      40             : using ::com::sun::star::uno::Reference;
      41             : using ::com::sun::star::uno::Sequence;
      42             : using ::rtl::OUString;
      43             : 
      44             : #if OSL_DEBUG_LEVEL > 1
      45             : namespace
      46             : {
      47             : void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource );
      48             : }
      49             : #endif
      50             : 
      51             : namespace chart
      52             : {
      53             : 
      54          41 : DataInterpreter::DataInterpreter(
      55             :     const Reference< uno::XComponentContext > & xContext ) :
      56          41 :         m_xContext( xContext )
      57          41 : {}
      58             : 
      59          82 : DataInterpreter::~DataInterpreter()
      60          82 : {}
      61             : 
      62         123 : Reference< uno::XComponentContext > DataInterpreter::GetComponentContext() const
      63             : {
      64         123 :     return m_xContext;
      65             : }
      66             : 
      67             : // ____ XDataInterpreter ____
      68          41 : InterpretedData SAL_CALL DataInterpreter::interpretDataSource(
      69             :     const Reference< data::XDataSource >& xSource,
      70             :     const Sequence< beans::PropertyValue >& aArguments,
      71             :     const Sequence< Reference< XDataSeries > >& aSeriesToReUse )
      72             :     throw (uno::RuntimeException)
      73             : {
      74          41 :     if( ! xSource.is())
      75           0 :         return InterpretedData();
      76             : 
      77             : #if OSL_DEBUG_LEVEL > 1
      78             :     lcl_ShowDataSource( xSource );
      79             : #endif
      80             : 
      81          41 :     Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() );
      82             : 
      83          41 :     Reference< data::XLabeledDataSequence > xCategories;
      84          41 :     vector< Reference< data::XLabeledDataSequence > > aSequencesVec;
      85             : 
      86             :     // check if we should use categories
      87             : 
      88          41 :     bool bHasCategories( HasCategories( aArguments, aData ));
      89             : 
      90             :     // parse data
      91          41 :     bool bCategoriesUsed = false;
      92         205 :     for( sal_Int32 i=0; i < aData.getLength(); ++i )
      93             :     {
      94             :         try
      95             :         {
      96         164 :             if( bHasCategories && ! bCategoriesUsed )
      97             :             {
      98          41 :                 xCategories.set( aData[i] );
      99          41 :                 if( xCategories.is())
     100          41 :                     SetRole( xCategories->getValues(), C2U("categories"));
     101          41 :                 bCategoriesUsed = true;
     102             :             }
     103             :             else
     104             :             {
     105         123 :                 aSequencesVec.push_back( aData[i] );
     106         123 :                 if( aData[i].is())
     107         123 :                     SetRole( aData[i]->getValues(), C2U("values-y"));
     108             :             }
     109             :         }
     110           0 :         catch( const uno::Exception & ex )
     111             :         {
     112             :             ASSERT_EXCEPTION( ex );
     113             :         }
     114             :     }
     115             : 
     116             :     // create DataSeries
     117             :     vector< Reference< data::XLabeledDataSequence > >::const_iterator
     118          41 :           aSequencesVecIt = aSequencesVec.begin();
     119             : 
     120          41 :     sal_Int32 nSeriesIndex = 0;
     121          41 :     vector< Reference< XDataSeries > > aSeriesVec;
     122          41 :     aSeriesVec.reserve( aSequencesVec.size());
     123             : 
     124         164 :     for( ;aSequencesVecIt != aSequencesVec.end(); ++aSequencesVecIt, ++nSeriesIndex )
     125             :     {
     126         123 :         Sequence< Reference< data::XLabeledDataSequence > > aNewData( & (*aSequencesVecIt), 1 );
     127         123 :         Reference< XDataSeries > xSeries;
     128         123 :         if( nSeriesIndex < aSeriesToReUse.getLength())
     129           0 :             xSeries.set( aSeriesToReUse[nSeriesIndex] );
     130             :         else
     131         123 :             xSeries.set( new DataSeries( GetComponentContext() ));
     132             :         OSL_ASSERT( xSeries.is() );
     133         123 :         Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY );
     134             :         OSL_ASSERT( xSink.is() );
     135         123 :         xSink->setData( aNewData );
     136             : 
     137         123 :         aSeriesVec.push_back( xSeries );
     138         123 :     }
     139             : 
     140          41 :     Sequence< Sequence< Reference< XDataSeries > > > aSeries(1);
     141          41 :     aSeries[0] = ContainerToSequence( aSeriesVec );
     142          41 :     return InterpretedData( aSeries, xCategories );
     143             : }
     144             : 
     145           0 : InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries(
     146             :     const InterpretedData& aInterpretedData )
     147             :     throw (uno::RuntimeException)
     148             : {
     149           0 :     InterpretedData aResult( aInterpretedData );
     150             : 
     151           0 :     sal_Int32 i=0;
     152           0 :     Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
     153           0 :     const sal_Int32 nCount = aSeries.getLength();
     154           0 :     for( ; i<nCount; ++i )
     155             :     {
     156             :         try
     157             :         {
     158           0 :             Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW );
     159           0 :             Sequence< Reference< data::XLabeledDataSequence > > aNewSequences;
     160             : 
     161             :             // values-y
     162             :             Reference< data::XLabeledDataSequence > xValuesY(
     163           0 :                 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false ));
     164             :             // re-use values-... as values-y
     165           0 :             if( ! xValuesY.is())
     166             :             {
     167             :                 xValuesY.set(
     168           0 :                     DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values"), true ));
     169           0 :                 if( xValuesY.is())
     170           0 :                     SetRole( xValuesY->getValues(), C2U("values-y"));
     171             :             }
     172           0 :             if( xValuesY.is())
     173             :             {
     174           0 :                 aNewSequences.realloc(1);
     175           0 :                 aNewSequences[0] = xValuesY;
     176             :             }
     177             : 
     178           0 :             Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences());
     179           0 :             if( aSeqs.getLength() != aNewSequences.getLength() )
     180             :             {
     181             : #if OSL_DEBUG_LEVEL > 1
     182             :                 sal_Int32 j=0;
     183             :                 for( ; j<aSeqs.getLength(); ++j )
     184             :                 {
     185             :                     OSL_ENSURE( aSeqs[j] == xValuesY, "All sequences should be used" );
     186             :                 }
     187             : #endif
     188           0 :                 Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW );
     189           0 :                 xSink->setData( aNewSequences );
     190           0 :             }
     191             :         }
     192           0 :         catch( const uno::Exception & ex )
     193             :         {
     194             :             ASSERT_EXCEPTION( ex );
     195             :         }
     196             :     }
     197             : 
     198           0 :     return aResult;
     199             : }
     200             : 
     201             : // criterion: all series must have exactly one data::XLabeledDataSequence
     202           0 : sal_Bool SAL_CALL DataInterpreter::isDataCompatible(
     203             :     const chart2::InterpretedData& aInterpretedData )
     204             :     throw (uno::RuntimeException)
     205             : {
     206           0 :     Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
     207           0 :     for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
     208             :     {
     209             :         try
     210             :         {
     211           0 :             Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW );
     212           0 :             Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
     213           0 :             if( aSeq.getLength() != 1 )
     214           0 :                 return sal_False;
     215             :         }
     216           0 :         catch( const uno::Exception & ex )
     217             :         {
     218             :             ASSERT_EXCEPTION( ex );
     219             :         }
     220             :     }
     221             : 
     222           0 :     return sal_True;
     223             : }
     224             : 
     225             : namespace
     226             : {
     227             : 
     228           0 : struct lcl_LabeledSequenceEquals : public std::unary_function< Reference< data::XLabeledDataSequence >, bool >
     229             : {
     230           0 :     lcl_LabeledSequenceEquals( const Reference< data::XLabeledDataSequence > & xLSeqToCmp ) :
     231             :             m_bHasLabels ( false ),
     232           0 :             m_bHasValues ( false )
     233             :     {
     234           0 :         if( xLSeqToCmp.is())
     235             :         {
     236           0 :             Reference< data::XDataSequence > xSeq( xLSeqToCmp->getValues());
     237           0 :             if( xSeq.is())
     238             :             {
     239           0 :                 m_bHasValues = true;
     240           0 :                 m_aValuesRangeRep = xSeq->getSourceRangeRepresentation();
     241             :             }
     242             : 
     243           0 :             xSeq.set( xLSeqToCmp->getLabel());
     244           0 :             if( xSeq.is())
     245             :             {
     246           0 :                 m_bHasLabels = true;
     247           0 :                 m_aLabelRangeRep = xSeq->getSourceRangeRepresentation();
     248           0 :             }
     249             :         }
     250           0 :     }
     251             : 
     252           0 :     bool operator() ( const Reference< data::XLabeledDataSequence > & xSeq )
     253             :     {
     254           0 :         if( ! xSeq.is())
     255           0 :             return false;
     256             : 
     257           0 :         Reference< data::XDataSequence > xSeqValues( xSeq->getValues() );
     258           0 :         Reference< data::XDataSequence > xSeqLabels( xSeq->getLabel() );
     259           0 :         bool bHasValues = xSeqValues.is();
     260           0 :         bool bHasLabels = xSeqLabels.is();
     261             : 
     262             :         return ( ( (m_bHasValues == bHasValues) &&
     263           0 :                    (!bHasValues || m_aValuesRangeRep.equals( xSeqValues->getSourceRangeRepresentation())) ) &&
     264             :                  ( (m_bHasLabels == bHasLabels) &&
     265           0 :                    (!bHasLabels || m_aLabelRangeRep.equals( xSeqLabels->getSourceRangeRepresentation())) )
     266           0 :             );
     267             :     }
     268             : 
     269             : private:
     270             :     bool m_bHasLabels;
     271             :     bool m_bHasValues;
     272             :     OUString m_aValuesRangeRep;
     273             :     OUString m_aLabelRangeRep;
     274             : };
     275             : 
     276             : } // anonymous namespace
     277             : 
     278           0 : Reference< data::XDataSource > SAL_CALL DataInterpreter::mergeInterpretedData(
     279             :     const InterpretedData& aInterpretedData )
     280             :     throw (uno::RuntimeException)
     281             : {
     282           0 :     vector< Reference< data::XLabeledDataSequence > > aResultVec;
     283           0 :     aResultVec.reserve( aInterpretedData.Series.getLength() +
     284             :                         1 // categories
     285           0 :         );
     286             : 
     287           0 :     if( aInterpretedData.Categories.is())
     288           0 :         aResultVec.push_back( aInterpretedData.Categories );
     289             : 
     290           0 :     Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
     291           0 :     for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
     292             :     {
     293             :         try
     294             :         {
     295           0 :             Reference< data::XDataSource > xSrc( aSeries[nSeriesIdx], uno::UNO_QUERY_THROW );
     296           0 :             Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
     297             : 
     298             :             // add all sequences of data series
     299           0 :             for( sal_Int32 nSeqIdx=0; nSeqIdx<aSeq.getLength(); ++nSeqIdx )
     300             :             {
     301           0 :                 Reference< data::XLabeledDataSequence > xAdd( aSeq[nSeqIdx] );
     302             : 
     303             :                 // only add if sequence is not yet in the result
     304           0 :                 if( find_if( aResultVec.begin(), aResultVec.end(),
     305           0 :                              lcl_LabeledSequenceEquals( xAdd )) == aResultVec.end())
     306             :                 {
     307           0 :                     aResultVec.push_back( xAdd );
     308             :                 }
     309           0 :             }
     310             :         }
     311           0 :         catch( const uno::Exception & ex )
     312             :         {
     313             :             ASSERT_EXCEPTION( ex );
     314             :         }
     315             :     }
     316             : 
     317           0 :     return Reference< data::XDataSource >( DataSourceHelper::createDataSource( ContainerToSequence( aResultVec ) ) );
     318             : }
     319             : 
     320             : // convenience methods
     321             : 
     322           0 : OUString DataInterpreter::GetRole( const Reference< data::XDataSequence > & xSeq )
     323             : {
     324           0 :     OUString aResult;
     325           0 :     if( ! xSeq.is())
     326           0 :         return aResult;
     327             : 
     328             :     try
     329             :     {
     330           0 :         Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
     331           0 :         xProp->getPropertyValue( C2U("Role")) >>= aResult;
     332             :     }
     333           0 :     catch( const uno::Exception & ex )
     334             :     {
     335             :         ASSERT_EXCEPTION( ex );
     336             :     }
     337           0 :     return aResult;
     338             : }
     339             : 
     340         164 : void DataInterpreter::SetRole( const Reference< data::XDataSequence > & xSeq, const OUString & rRole )
     341             : {
     342         164 :     if( ! xSeq.is())
     343         164 :         return;
     344             :     try
     345             :     {
     346         164 :         Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
     347         164 :         xProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
     348             :     }
     349           0 :     catch( const uno::Exception & ex )
     350             :     {
     351             :         ASSERT_EXCEPTION( ex );
     352             :     }
     353             : }
     354             : 
     355          41 : uno::Any DataInterpreter::GetProperty(
     356             :     const Sequence< beans::PropertyValue > & aArguments,
     357             :     const OUString & rName )
     358             : {
     359          82 :     for( sal_Int32 i=aArguments.getLength(); i--; )
     360             :     {
     361          41 :         if( aArguments[i].Name.equals( rName ))
     362          41 :             return aArguments[i].Value;
     363             :     }
     364           0 :     return uno::Any();
     365             : }
     366             : 
     367          41 : bool DataInterpreter::HasCategories(
     368             :     const Sequence< beans::PropertyValue > & rArguments,
     369             :     const Sequence< Reference< data::XLabeledDataSequence > > & rData )
     370             : {
     371          41 :     bool bHasCategories = false;
     372             : 
     373          41 :     if( rArguments.getLength() > 0 )
     374          41 :         GetProperty( rArguments, C2U(("HasCategories"))) >>= bHasCategories;
     375             : 
     376          41 :     for( sal_Int32 nLSeqIdx=0; ! bHasCategories && nLSeqIdx<rData.getLength(); ++nLSeqIdx )
     377           0 :         bHasCategories = ( rData[nLSeqIdx].is() && GetRole( rData[nLSeqIdx]->getValues() ) == "categories");
     378             : 
     379          41 :     return bHasCategories;
     380             : }
     381             : 
     382           0 : bool DataInterpreter::UseCategoriesAsX( const Sequence< beans::PropertyValue > & rArguments )
     383             : {
     384           0 :     bool bUseCategoriesAsX = true;
     385           0 :     if( rArguments.getLength() > 0 )
     386           0 :         GetProperty( rArguments, C2U(("UseCategoriesAsX"))) >>= bUseCategoriesAsX;
     387           0 :     return bUseCategoriesAsX;
     388             : }
     389             : 
     390             : // ------------------------------------------------------------
     391             : 
     392           0 : Sequence< OUString > DataInterpreter::getSupportedServiceNames_Static()
     393             : {
     394           0 :     Sequence< OUString > aServices( 1 );
     395           0 :     aServices[0] = C2U( "com.sun.star.chart2.DataInterpreter" );
     396           0 :     return aServices;
     397             : }
     398             : 
     399             : // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
     400           0 : APPHELPER_XSERVICEINFO_IMPL( DataInterpreter, C2U("com.sun.star.comp.chart2.DataInterpreter"));
     401             : 
     402             : } // namespace chart
     403             : 
     404             : #if OSL_DEBUG_LEVEL > 1
     405             : namespace
     406             : {
     407             : 
     408             : void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource )
     409             : {
     410             :     if( ! xSource.is())
     411             :         return;
     412             : 
     413             :     OSL_TRACE( "DataSource in DataInterpreter:" );
     414             :     Sequence< Reference< data::XLabeledDataSequence > > aSequences( xSource->getDataSequences());
     415             :     Reference< beans::XPropertySet > xProp;
     416             :     OUString aId;
     417             :     const sal_Int32 nMax = aSequences.getLength();
     418             :     for( sal_Int32 k = 0; k < nMax; ++k )
     419             :     {
     420             :         if( aSequences[k].is())
     421             :         {
     422             :             OUString aSourceRepr(C2U("<none>"));
     423             :             if( aSequences[k]->getValues().is())
     424             :                 aSourceRepr = aSequences[k]->getValues()->getSourceRangeRepresentation();
     425             :             xProp.set( aSequences[k]->getValues(), uno::UNO_QUERY );
     426             :             if( xProp.is() &&
     427             :                 ( xProp->getPropertyValue( C2U( "Role" )) >>= aId ))
     428             :             {
     429             :                 OSL_TRACE( "  <data sequence %d> Role: %s, Source: %s", k, U2C( aId ), U2C( aSourceRepr ));
     430             :             }
     431             :             else
     432             :             {
     433             :                 OSL_TRACE( "  <data sequence %d> unknown Role, Source: %s", k, U2C( aSourceRepr ) );
     434             :             }
     435             : 
     436             :             aSourceRepr = C2U("<none>");
     437             :             if( aSequences[k]->getLabel().is())
     438             :                 aSourceRepr = OUString( aSequences[k]->getLabel()->getSourceRangeRepresentation());
     439             :             xProp.set( aSequences[k]->getLabel(), uno::UNO_QUERY );
     440             :             if( xProp.is() &&
     441             :                 ( xProp->getPropertyValue( C2U( "Role" )) >>= aId ))
     442             :             {
     443             :                 OSL_TRACE( "  <data sequence label %d> Role: %s, Source: %s", k, U2C( aId ), U2C( aSourceRepr ));
     444             :             }
     445             :             else
     446             :             {
     447             :                 OSL_TRACE( "  <data sequence label %d> unknown Role, Source: %s", k, U2C( aSourceRepr ) );
     448             :             }
     449             :         }
     450             :     }
     451             : }
     452             : 
     453             : }
     454             : #endif
     455             : 
     456             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10