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 
BubbleDataInterpreter(const uno::Reference<uno::XComponentContext> & xContext)48 BubbleDataInterpreter::BubbleDataInterpreter(
49     const uno::Reference< uno::XComponentContext > & xContext ) :
50         DataInterpreter( xContext )
51 {
52 }
53 
~BubbleDataInterpreter()54 BubbleDataInterpreter::~BubbleDataInterpreter()
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 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 
reinterpretDataSeries(const chart2::InterpretedData & aInterpretedData)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 
isDataCompatible(const chart2::InterpretedData & aInterpretedData)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