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

Generated by: LCOV version 1.10