1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_chart2.hxx" 26 27 #include "BubbleDataInterpreter.hxx" 28 #include "DataSeries.hxx" 29 #include "macros.hxx" 30 #include "DataSeriesHelper.hxx" 31 #include "CommonConverters.hxx" 32 #include "ContainerHelper.hxx" 33 #include <com/sun/star/beans/XPropertySet.hpp> 34 #include <com/sun/star/chart2/data/XDataSink.hpp> 35 #include <com/sun/star/util/XCloneable.hpp> 36 37 using namespace ::com::sun::star; 38 using namespace ::com::sun::star::chart2; 39 using namespace ::std; 40 41 using ::com::sun::star::uno::Reference; 42 using ::com::sun::star::uno::Sequence; 43 using ::rtl::OUString; 44 45 namespace chart 46 { 47 48 BubbleDataInterpreter::BubbleDataInterpreter( 49 const uno::Reference< uno::XComponentContext > & xContext ) : 50 DataInterpreter( xContext ) 51 { 52 } 53 54 BubbleDataInterpreter::~BubbleDataInterpreter() 55 { 56 } 57 58 // ____ XDataInterpreter ____ 59 chart2::InterpretedData SAL_CALL BubbleDataInterpreter::interpretDataSource( 60 const Reference< chart2::data::XDataSource >& xSource, 61 const Sequence< beans::PropertyValue >& aArguments, 62 const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) 63 throw (uno::RuntimeException) 64 { 65 if( ! xSource.is()) 66 return InterpretedData(); 67 68 Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); 69 70 Reference< data::XLabeledDataSequence > xValuesX; 71 vector< Reference< data::XLabeledDataSequence > > aYValuesVector; 72 vector< Reference< data::XLabeledDataSequence > > aSizeValuesVector; 73 74 Reference< data::XLabeledDataSequence > xCategories; 75 bool bHasCategories = HasCategories( aArguments, aData ); 76 bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); 77 78 bool bSetXValues = false; 79 sal_Int32 nDataSeqCount = aData.getLength(); 80 81 bSetXValues = bHasCategories ? ( (nDataSeqCount-1) > 2 && (nDataSeqCount-1) % 2 != 0 ) 82 :( nDataSeqCount > 2 && nDataSeqCount % 2 != 0 ); 83 84 bool bCategoriesUsed = false; 85 bool bNextIsYValues = bHasCategories ? nDataSeqCount>2 : nDataSeqCount>1; 86 for( sal_Int32 nDataIdx = 0; nDataIdx < nDataSeqCount; ++nDataIdx ) 87 { 88 try 89 { 90 if( bHasCategories && !bCategoriesUsed ) 91 { 92 xCategories.set( aData[nDataIdx] ); 93 if( xCategories.is()) 94 { 95 SetRole( xCategories->getValues(), C2U("categories")); 96 if( bUseCategoriesAsX ) 97 { 98 bSetXValues = false; 99 bNextIsYValues = nDataSeqCount > 2; 100 } 101 } 102 bCategoriesUsed = true; 103 } 104 else if( !xValuesX.is() && bSetXValues ) 105 { 106 xValuesX.set( aData[nDataIdx] ); 107 if( xValuesX.is()) 108 SetRole( xValuesX->getValues(), C2U("values-x")); 109 } 110 else if( bNextIsYValues ) 111 { 112 aYValuesVector.push_back( aData[nDataIdx] ); 113 if( aData[nDataIdx].is()) 114 SetRole( aData[nDataIdx]->getValues(), C2U("values-y")); 115 bNextIsYValues = false; 116 } 117 else if( !bNextIsYValues ) 118 { 119 aSizeValuesVector.push_back( aData[nDataIdx] ); 120 if( aData[nDataIdx].is()) 121 SetRole( aData[nDataIdx]->getValues(), C2U("values-size")); 122 bNextIsYValues = (nDataSeqCount-(nDataIdx+1)) >= 2;//two or more left 123 } 124 } 125 catch( uno::Exception & ex ) 126 { 127 ASSERT_EXCEPTION( ex ); 128 } 129 } 130 131 // create DataSeries 132 sal_Int32 nSeriesIndex = 0; 133 vector< Reference< XDataSeries > > aSeriesVec; 134 aSeriesVec.reserve( aSizeValuesVector.size()); 135 136 Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; 137 Reference< util::XCloneable > xCloneableX( xValuesX, uno::UNO_QUERY ); 138 139 for( size_t nN = 0; nN < aSizeValuesVector.size(); ++nN, ++nSeriesIndex ) 140 { 141 vector< Reference< data::XLabeledDataSequence > > aNewData; 142 if( xValuesX.is() ) 143 { 144 if( nN > 0 && xCloneableX.is() ) 145 xClonedXValues.set( xCloneableX->createClone(), uno::UNO_QUERY ); 146 aNewData.push_back( xClonedXValues ); 147 } 148 if( aYValuesVector.size() > nN ) 149 aNewData.push_back( aYValuesVector[nN] ); 150 if( aSizeValuesVector.size() > nN ) 151 aNewData.push_back( aSizeValuesVector[nN] ); 152 153 Reference< XDataSeries > xSeries; 154 if( nSeriesIndex < aSeriesToReUse.getLength()) 155 xSeries.set( aSeriesToReUse[nSeriesIndex] ); 156 else 157 xSeries.set( new DataSeries( GetComponentContext() ) ); 158 OSL_ASSERT( xSeries.is() ); 159 Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); 160 OSL_ASSERT( xSink.is() ); 161 xSink->setData( ContainerHelper::ContainerToSequence( aNewData ) ); 162 163 aSeriesVec.push_back( xSeries ); 164 } 165 166 Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); 167 aSeries[0] = ContainerHelper::ContainerToSequence( aSeriesVec ); 168 return InterpretedData( aSeries, xCategories ); 169 } 170 171 chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( 172 const chart2::InterpretedData& aInterpretedData ) 173 throw (uno::RuntimeException) 174 { 175 InterpretedData aResult( aInterpretedData ); 176 177 sal_Int32 i=0; 178 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); 179 const sal_Int32 nCount = aSeries.getLength(); 180 for( ; i<nCount; ++i ) 181 { 182 try 183 { 184 Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); 185 Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; 186 187 Reference< data::XLabeledDataSequence > xValuesSize( 188 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-size"), false )); 189 Reference< data::XLabeledDataSequence > xValuesY( 190 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false )); 191 Reference< data::XLabeledDataSequence > xValuesX( 192 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-x"), false )); 193 194 if( ! xValuesX.is() || 195 ! xValuesY.is() || 196 ! xValuesSize.is() ) 197 { 198 vector< Reference< data::XLabeledDataSequence > > aValueSeqVec( 199 DataSeriesHelper::getAllDataSequencesByRole( 200 xSeriesSource->getDataSequences(), C2U("values"), true )); 201 if( xValuesX.is()) 202 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX )); 203 if( xValuesY.is()) 204 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY )); 205 if( xValuesSize.is()) 206 aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesSize )); 207 208 size_t nIndex = 0; 209 210 if( ! xValuesSize.is() && 211 aValueSeqVec.size() > nIndex ) 212 { 213 xValuesSize.set( aValueSeqVec[nIndex++] ); 214 if( xValuesSize.is()) 215 SetRole( xValuesSize->getValues(), C2U("values-size")); 216 } 217 218 if( ! xValuesY.is() && 219 aValueSeqVec.size() > nIndex ) 220 { 221 xValuesY.set( aValueSeqVec[nIndex++] ); 222 if( xValuesY.is()) 223 SetRole( xValuesY->getValues(), C2U("values-y")); 224 } 225 226 if( ! xValuesX.is() && 227 aValueSeqVec.size() > nIndex ) 228 { 229 xValuesX.set( aValueSeqVec[nIndex++] ); 230 if( xValuesX.is()) 231 SetRole( xValuesY->getValues(), C2U("values-x")); 232 } 233 } 234 if( xValuesSize.is()) 235 { 236 if( xValuesY.is() ) 237 { 238 if( xValuesX.is() ) 239 { 240 aNewSequences.realloc(3); 241 aNewSequences[0] = xValuesX; 242 aNewSequences[1] = xValuesY; 243 aNewSequences[2] = xValuesSize; 244 } 245 else 246 { 247 aNewSequences.realloc(2); 248 aNewSequences[0] = xValuesY; 249 aNewSequences[1] = xValuesSize; 250 } 251 } 252 else 253 { 254 aNewSequences.realloc(1); 255 aNewSequences[0] = xValuesSize; 256 } 257 } 258 259 Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); 260 if( aSeqs.getLength() != aNewSequences.getLength() ) 261 { 262 #if OSL_DEBUG_LEVEL > 1 263 sal_Int32 j=0; 264 for( ; j<aSeqs.getLength(); ++j ) 265 { 266 OSL_ENSURE( aSeqs[j] == xValuesY || aSeqs[j] == xValuesX || aSeqs[j] == xValuesSize, "All sequences should be used" ); 267 } 268 #endif 269 Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); 270 xSink->setData( aNewSequences ); 271 } 272 } 273 catch( uno::Exception & ex ) 274 { 275 ASSERT_EXCEPTION( ex ); 276 } 277 } 278 279 return aResult; 280 } 281 282 sal_Bool SAL_CALL BubbleDataInterpreter::isDataCompatible( 283 const chart2::InterpretedData& aInterpretedData ) 284 throw (uno::RuntimeException) 285 { 286 Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); 287 for( sal_Int32 i=0; i<aSeries.getLength(); ++i ) 288 { 289 try 290 { 291 Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW ); 292 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); 293 if( aSeq.getLength() != 3 ) 294 return sal_False; 295 } 296 catch( uno::Exception & ex ) 297 { 298 ASSERT_EXCEPTION( ex ); 299 } 300 } 301 302 return sal_True; 303 } 304 305 } // namespace chart 306