xref: /trunk/main/chart2/source/model/template/BubbleDataInterpreter.cxx (revision 9c15e1abd703a7953928d7a80655ae1a76a41f6d)
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