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

Generated by: LCOV version 1.11