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 "BubbleDataInterpreter.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 BubbleDataInterpreter::BubbleDataInterpreter( 53 const uno::Reference< uno::XComponentContext > & xContext ) : 54 DataInterpreter( xContext ) 55 { 56 } 57 58 BubbleDataInterpreter::~BubbleDataInterpreter() 59 { 60 } 61 62 // ____ XDataInterpreter ____ 63 chart2::InterpretedData SAL_CALL BubbleDataInterpreter::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 > > aYValuesVector; 76 vector< Reference< data::XLabeledDataSequence > > aSizeValuesVector; 77 78 Reference< data::XLabeledDataSequence > xCategories; 79 bool bHasCategories = HasCategories( aArguments, aData ); 80 bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); 81 82 bool bSetXValues = false; 83 sal_Int32 nDataSeqCount = aData.getLength(); 84 85 bSetXValues = bHasCategories ? ( (nDataSeqCount-1) > 2 && (nDataSeqCount-1) % 2 != 0 ) 86 :( nDataSeqCount > 2 && nDataSeqCount % 2 != 0 ); 87 88 bool bCategoriesUsed = false; 89 bool bNextIsYValues = bHasCategories ? nDataSeqCount>2 : nDataSeqCount>1; 90 for( sal_Int32 nDataIdx = 0; nDataIdx < nDataSeqCount; ++nDataIdx ) 91 { 92 try 93 { 94 if( bHasCategories && !bCategoriesUsed ) 95 { 96 xCategories.set( aData[nDataIdx] ); 97 if( xCategories.is()) 98 { 99 SetRole( xCategories->getValues(), C2U("categories")); 100 if( bUseCategoriesAsX ) 101 { 102 bSetXValues = false; 103 bNextIsYValues = nDataSeqCount > 2; 104 } 105 } 106 bCategoriesUsed = true; 107 } 108 else if( !xValuesX.is() && bSetXValues ) 109 { 110 xValuesX.set( aData[nDataIdx] ); 111 if( xValuesX.is()) 112 SetRole( xValuesX->getValues(), C2U("values-x")); 113 } 114 else if( bNextIsYValues ) 115 { 116 aYValuesVector.push_back( aData[nDataIdx] ); 117 if( aData[nDataIdx].is()) 118 SetRole( aData[nDataIdx]->getValues(), C2U("values-y")); 119 bNextIsYValues = false; 120 } 121 else if( !bNextIsYValues ) 122 { 123 aSizeValuesVector.push_back( aData[nDataIdx] ); 124 if( aData[nDataIdx].is()) 125 SetRole( aData[nDataIdx]->getValues(), C2U("values-size")); 126 bNextIsYValues = (nDataSeqCount-(nDataIdx+1)) >= 2;//two or more left 127 } 128 } 129 catch( uno::Exception & ex ) 130 { 131 ASSERT_EXCEPTION( ex ); 132 } 133 } 134 135 // create DataSeries 136 sal_Int32 nSeriesIndex = 0; 137 vector< Reference< XDataSeries > > aSeriesVec; 138 aSeriesVec.reserve( aSizeValuesVector.size()); 139 140 Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; 141 Reference< util::XCloneable > xCloneableX( xValuesX, uno::UNO_QUERY ); 142 143 for( size_t nN = 0; nN < aSizeValuesVector.size(); ++nN, ++nSeriesIndex ) 144 { 145 vector< Reference< data::XLabeledDataSequence > > aNewData; 146 if( xValuesX.is() ) 147 { 148 if( nN > 0 && xCloneableX.is() ) 149 xClonedXValues.set( xCloneableX->createClone(), uno::UNO_QUERY ); 150 aNewData.push_back( xClonedXValues ); 151 } 152 if( aYValuesVector.size() > nN ) 153 aNewData.push_back( aYValuesVector[nN] ); 154 if( aSizeValuesVector.size() > nN ) 155 aNewData.push_back( aSizeValuesVector[nN] ); 156 157 Reference< XDataSeries > xSeries; 158 if( nSeriesIndex < aSeriesToReUse.getLength()) 159 xSeries.set( aSeriesToReUse[nSeriesIndex] ); 160 else 161 xSeries.set( new DataSeries( GetComponentContext() ) ); 162 OSL_ASSERT( xSeries.is() ); 163 Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); 164 OSL_ASSERT( xSink.is() ); 165 xSink->setData( ContainerHelper::ContainerToSequence( aNewData ) ); 166 167 aSeriesVec.push_back( xSeries ); 168 } 169 170 Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); 171 aSeries[0] = ContainerHelper::ContainerToSequence( aSeriesVec ); 172 return InterpretedData( aSeries, xCategories ); 173 } 174 175 chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( 176 const chart2::InterpretedData& aInterpretedData ) 177 throw (uno::RuntimeException) 178 { 179 InterpretedData aResult( aInterpretedData ); 180 181 sal_Int32 i=0; 182 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); 183 const sal_Int32 nCount = aSeries.getLength(); 184 for( ; i<nCount; ++i ) 185 { 186 try 187 { 188 Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); 189 Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; 190 191 Reference< data::XLabeledDataSequence > xValuesSize( 192 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-size"), false )); 193 Reference< data::XLabeledDataSequence > xValuesY( 194 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false )); 195 Reference< data::XLabeledDataSequence > xValuesX( 196 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-x"), false )); 197 198 if( ! xValuesX.is() || 199 ! xValuesY.is() || 200 ! xValuesSize.is() ) 201 { 202 vector< Reference< data::XLabeledDataSequence > > aValueSeqVec( 203 DataSeriesHelper::getAllDataSequencesByRole( 204 xSeriesSource->getDataSequences(), C2U("values"), true )); 205 if( xValuesX.is()) 206 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX )); 207 if( xValuesY.is()) 208 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY )); 209 if( xValuesSize.is()) 210 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesSize )); 211 212 size_t nIndex = 0; 213 214 if( ! xValuesSize.is() && 215 aValueSeqVec.size() > nIndex ) 216 { 217 xValuesSize.set( aValueSeqVec[nIndex++] ); 218 if( xValuesSize.is()) 219 SetRole( xValuesSize->getValues(), C2U("values-size")); 220 } 221 222 if( ! xValuesY.is() && 223 aValueSeqVec.size() > nIndex ) 224 { 225 xValuesY.set( aValueSeqVec[nIndex++] ); 226 if( xValuesY.is()) 227 SetRole( xValuesY->getValues(), C2U("values-y")); 228 } 229 230 if( ! xValuesX.is() && 231 aValueSeqVec.size() > nIndex ) 232 { 233 xValuesX.set( aValueSeqVec[nIndex++] ); 234 if( xValuesX.is()) 235 SetRole( xValuesY->getValues(), C2U("values-x")); 236 } 237 } 238 if( xValuesSize.is()) 239 { 240 if( xValuesY.is() ) 241 { 242 if( xValuesX.is() ) 243 { 244 aNewSequences.realloc(3); 245 aNewSequences[0] = xValuesX; 246 aNewSequences[1] = xValuesY; 247 aNewSequences[2] = xValuesSize; 248 } 249 else 250 { 251 aNewSequences.realloc(2); 252 aNewSequences[0] = xValuesY; 253 aNewSequences[1] = xValuesSize; 254 } 255 } 256 else 257 { 258 aNewSequences.realloc(1); 259 aNewSequences[0] = xValuesSize; 260 } 261 } 262 263 Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); 264 if( aSeqs.getLength() != aNewSequences.getLength() ) 265 { 266 #if OSL_DEBUG_LEVEL > 1 267 sal_Int32 j=0; 268 for( ; j<aSeqs.getLength(); ++j ) 269 { 270 OSL_ENSURE( aSeqs[j] == xValuesY || aSeqs[j] == xValuesX || aSeqs[j] == xValuesSize, "All sequences should be used" ); 271 } 272 #endif 273 Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); 274 xSink->setData( aNewSequences ); 275 } 276 } 277 catch( uno::Exception & ex ) 278 { 279 ASSERT_EXCEPTION( ex ); 280 } 281 } 282 283 return aResult; 284 } 285 286 sal_Bool SAL_CALL BubbleDataInterpreter::isDataCompatible( 287 const chart2::InterpretedData& aInterpretedData ) 288 throw (uno::RuntimeException) 289 { 290 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); 291 for( sal_Int32 i=0; i<aSeries.getLength(); ++i ) 292 { 293 try 294 { 295 Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW ); 296 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); 297 if( aSeq.getLength() != 3 ) 298 return sal_False; 299 } 300 catch( uno::Exception & ex ) 301 { 302 ASSERT_EXCEPTION( ex ); 303 } 304 } 305 306 return sal_True; 307 } 308 309 } // namespace chart 310