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
XYDataInterpreter(const uno::Reference<uno::XComponentContext> & xContext)48 XYDataInterpreter::XYDataInterpreter(
49 const uno::Reference< uno::XComponentContext > & xContext ) :
50 DataInterpreter( xContext )
51 {
52 }
53
~XYDataInterpreter()54 XYDataInterpreter::~XYDataInterpreter()
55 {
56 }
57
58 // ____ XDataInterpreter ____
interpretDataSource(const Reference<chart2::data::XDataSource> & xSource,const Sequence<beans::PropertyValue> & aArguments,const Sequence<Reference<XDataSeries>> & aSeriesToReUse)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
reinterpretDataSeries(const chart2::InterpretedData & aInterpretedData)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
isDataCompatible(const chart2::InterpretedData & aInterpretedData)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