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