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