1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 31 #include "XYDataInterpreter.hxx" 32 #include "DataSeries.hxx" 33 #include "macros.hxx" 34 #include "DataSeriesHelper.hxx" 35 #include "CommonConverters.hxx" 36 #include "ContainerHelper.hxx" 37 #include <com/sun/star/beans/XPropertySet.hpp> 38 #include <com/sun/star/chart2/data/XDataSink.hpp> 39 #include <com/sun/star/util/XCloneable.hpp> 40 41 using namespace ::com::sun::star; 42 using namespace ::com::sun::star::chart2; 43 using namespace ::std; 44 45 using ::com::sun::star::uno::Reference; 46 using ::com::sun::star::uno::Sequence; 47 using ::rtl::OUString; 48 49 namespace chart 50 { 51 52 XYDataInterpreter::XYDataInterpreter( 53 const uno::Reference< uno::XComponentContext > & xContext ) : 54 DataInterpreter( xContext ) 55 { 56 } 57 58 XYDataInterpreter::~XYDataInterpreter() 59 { 60 } 61 62 // ____ XDataInterpreter ____ 63 chart2::InterpretedData SAL_CALL XYDataInterpreter::interpretDataSource( 64 const Reference< chart2::data::XDataSource >& xSource, 65 const Sequence< beans::PropertyValue >& aArguments, 66 const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) 67 throw (uno::RuntimeException) 68 { 69 if( ! xSource.is()) 70 return InterpretedData(); 71 72 Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); 73 74 Reference< data::XLabeledDataSequence > xValuesX; 75 vector< Reference< data::XLabeledDataSequence > > aSequencesVec; 76 77 Reference< data::XLabeledDataSequence > xCategories; 78 bool bHasCategories = HasCategories( aArguments, aData ); 79 bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); 80 81 // parse data 82 bool bCategoriesUsed = false; 83 bool bSetXValues = aData.getLength()>(bCategoriesUsed?2:1); 84 for( sal_Int32 nDataIdx= 0; nDataIdx < aData.getLength(); ++nDataIdx ) 85 { 86 try 87 { 88 if( bHasCategories && ! bCategoriesUsed ) 89 { 90 xCategories.set( aData[nDataIdx] ); 91 if( xCategories.is()) 92 { 93 SetRole( xCategories->getValues(), C2U("categories")); 94 if( bUseCategoriesAsX ) 95 bSetXValues = false; 96 } 97 bCategoriesUsed = true; 98 } 99 else if( !xValuesX.is() && bSetXValues ) 100 { 101 xValuesX.set( aData[nDataIdx] ); 102 if( xValuesX.is()) 103 SetRole( xValuesX->getValues(), C2U("values-x")); 104 } 105 else 106 { 107 aSequencesVec.push_back( aData[nDataIdx] ); 108 if( aData[nDataIdx].is()) 109 SetRole( aData[nDataIdx]->getValues(), C2U("values-y")); 110 } 111 } 112 catch( uno::Exception & ex ) 113 { 114 ASSERT_EXCEPTION( ex ); 115 } 116 } 117 118 // create DataSeries 119 vector< Reference< data::XLabeledDataSequence > >::const_iterator 120 aSequencesVecIt = aSequencesVec.begin(); 121 122 sal_Int32 nSeriesIndex = 0; 123 vector< Reference< XDataSeries > > aSeriesVec; 124 aSeriesVec.reserve( aSequencesVec.size()); 125 126 Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; 127 Reference< util::XCloneable > xCloneable( xValuesX, uno::UNO_QUERY ); 128 129 for( ;aSequencesVecIt != aSequencesVec.end(); ++aSequencesVecIt, ++nSeriesIndex ) 130 { 131 vector< Reference< data::XLabeledDataSequence > > aNewData; 132 133 if( aSequencesVecIt != aSequencesVec.begin() && xCloneable.is() ) 134 xClonedXValues.set( xCloneable->createClone(), uno::UNO_QUERY ); 135 if( xValuesX.is() ) 136 aNewData.push_back( xClonedXValues ); 137 138 aNewData.push_back( *aSequencesVecIt ); 139 140 Reference< XDataSeries > xSeries; 141 if( nSeriesIndex < aSeriesToReUse.getLength()) 142 xSeries.set( aSeriesToReUse[nSeriesIndex] ); 143 else 144 xSeries.set( new DataSeries( GetComponentContext() ) ); 145 OSL_ASSERT( xSeries.is() ); 146 Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); 147 OSL_ASSERT( xSink.is() ); 148 xSink->setData( ContainerHelper::ContainerToSequence( aNewData ) ); 149 150 aSeriesVec.push_back( xSeries ); 151 } 152 153 Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); 154 aSeries[0] = ContainerHelper::ContainerToSequence( aSeriesVec ); 155 return InterpretedData( aSeries, xCategories ); 156 } 157 158 chart2::InterpretedData SAL_CALL XYDataInterpreter::reinterpretDataSeries( 159 const chart2::InterpretedData& aInterpretedData ) 160 throw (uno::RuntimeException) 161 { 162 InterpretedData aResult( aInterpretedData ); 163 164 sal_Int32 i=0; 165 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); 166 const sal_Int32 nCount = aSeries.getLength(); 167 for( ; i<nCount; ++i ) 168 { 169 try 170 { 171 Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); 172 Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; 173 174 // values-y 175 Reference< data::XLabeledDataSequence > xValuesY( 176 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false )); 177 Reference< data::XLabeledDataSequence > xValuesX( 178 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-x"), false )); 179 // re-use values-... as values-x/values-y 180 if( ! xValuesX.is() || 181 ! xValuesY.is()) 182 { 183 vector< Reference< data::XLabeledDataSequence > > aValueSeqVec( 184 DataSeriesHelper::getAllDataSequencesByRole( 185 xSeriesSource->getDataSequences(), C2U("values"), true )); 186 if( xValuesX.is()) 187 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX )); 188 if( xValuesY.is()) 189 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY )); 190 191 size_t nIndex = 0; 192 if( ! xValuesY.is() && 193 aValueSeqVec.size() > nIndex ) 194 { 195 xValuesY.set( aValueSeqVec[nIndex++] ); 196 if( xValuesY.is()) 197 SetRole( xValuesY->getValues(), C2U("values-y")); 198 } 199 200 if( ! xValuesX.is() && 201 aValueSeqVec.size() > nIndex ) 202 { 203 xValuesX.set( aValueSeqVec[nIndex++] ); 204 if( xValuesX.is()) 205 SetRole( xValuesY->getValues(), C2U("values-x")); 206 } 207 } 208 if( xValuesY.is()) 209 { 210 if( xValuesX.is()) 211 { 212 aNewSequences.realloc(2); 213 aNewSequences[0] = xValuesX; 214 aNewSequences[1] = xValuesY; 215 } 216 else 217 { 218 aNewSequences.realloc(1); 219 aNewSequences[0] = xValuesY; 220 } 221 } 222 223 Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); 224 if( aSeqs.getLength() != aNewSequences.getLength() ) 225 { 226 #if OSL_DEBUG_LEVEL > 1 227 sal_Int32 j=0; 228 for( ; j<aSeqs.getLength(); ++j ) 229 { 230 OSL_ENSURE( aSeqs[j] == xValuesY || aSeqs[j] == xValuesX, "All sequences should be used" ); 231 } 232 #endif 233 Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); 234 xSink->setData( aNewSequences ); 235 } 236 } 237 catch( uno::Exception & ex ) 238 { 239 ASSERT_EXCEPTION( ex ); 240 } 241 } 242 243 return aResult; 244 } 245 246 // criterion: all series must have exactly two data::XLabeledDataSequences 247 sal_Bool SAL_CALL XYDataInterpreter::isDataCompatible( 248 const chart2::InterpretedData& aInterpretedData ) 249 throw (uno::RuntimeException) 250 { 251 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); 252 for( sal_Int32 i=0; i<aSeries.getLength(); ++i ) 253 { 254 try 255 { 256 Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW ); 257 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); 258 if( aSeq.getLength() != 2 ) 259 return sal_False; 260 } 261 catch( uno::Exception & ex ) 262 { 263 ASSERT_EXCEPTION( ex ); 264 } 265 } 266 267 return sal_True; 268 } 269 270 } // namespace chart 271