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