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

Generated by: LCOV version 1.10