1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_chart2.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include "StockDataInterpreter.hxx"
28*b1cdbd2cSJim Jagielski #include "DataSeries.hxx"
29*b1cdbd2cSJim Jagielski #include "macros.hxx"
30*b1cdbd2cSJim Jagielski #include "DataSeriesHelper.hxx"
31*b1cdbd2cSJim Jagielski #include "CommonConverters.hxx"
32*b1cdbd2cSJim Jagielski #include "ContainerHelper.hxx"
33*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/XPropertySet.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/chart2/data/XDataSink.hpp>
35*b1cdbd2cSJim Jagielski 
36*b1cdbd2cSJim Jagielski // #include <deque>
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski #include <vector>
39*b1cdbd2cSJim Jagielski #include <algorithm>
40*b1cdbd2cSJim Jagielski #include <iterator>
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
43*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::chart2;
44*b1cdbd2cSJim Jagielski using namespace ::std;
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski using ::com::sun::star::uno::Reference;
47*b1cdbd2cSJim Jagielski using ::com::sun::star::uno::Sequence;
48*b1cdbd2cSJim Jagielski using ::rtl::OUString;
49*b1cdbd2cSJim Jagielski using namespace ::chart::ContainerHelper;
50*b1cdbd2cSJim Jagielski 
51*b1cdbd2cSJim Jagielski namespace chart
52*b1cdbd2cSJim Jagielski {
53*b1cdbd2cSJim Jagielski 
54*b1cdbd2cSJim Jagielski // explicit
StockDataInterpreter(StockChartTypeTemplate::StockVariant eVariant,const Reference<uno::XComponentContext> & xContext)55*b1cdbd2cSJim Jagielski StockDataInterpreter::StockDataInterpreter(
56*b1cdbd2cSJim Jagielski     StockChartTypeTemplate::StockVariant eVariant,
57*b1cdbd2cSJim Jagielski     const Reference< uno::XComponentContext > & xContext ) :
58*b1cdbd2cSJim Jagielski         DataInterpreter( xContext ),
59*b1cdbd2cSJim Jagielski         m_eStockVariant( eVariant )
60*b1cdbd2cSJim Jagielski {}
61*b1cdbd2cSJim Jagielski 
~StockDataInterpreter()62*b1cdbd2cSJim Jagielski StockDataInterpreter::~StockDataInterpreter()
63*b1cdbd2cSJim Jagielski {}
64*b1cdbd2cSJim Jagielski 
GetStockVariant() const65*b1cdbd2cSJim Jagielski StockChartTypeTemplate::StockVariant StockDataInterpreter::GetStockVariant() const
66*b1cdbd2cSJim Jagielski {
67*b1cdbd2cSJim Jagielski     return m_eStockVariant;
68*b1cdbd2cSJim Jagielski }
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski // ____ XDataInterpreter ____
interpretDataSource(const Reference<data::XDataSource> & xSource,const Sequence<beans::PropertyValue> & rArguments,const Sequence<Reference<XDataSeries>> & rSeriesToReUse)71*b1cdbd2cSJim Jagielski InterpretedData SAL_CALL StockDataInterpreter::interpretDataSource(
72*b1cdbd2cSJim Jagielski     const Reference< data::XDataSource >& xSource,
73*b1cdbd2cSJim Jagielski     const Sequence< beans::PropertyValue >& rArguments,
74*b1cdbd2cSJim Jagielski     const Sequence< Reference< XDataSeries > >& rSeriesToReUse )
75*b1cdbd2cSJim Jagielski     throw (uno::RuntimeException)
76*b1cdbd2cSJim Jagielski {
77*b1cdbd2cSJim Jagielski     if( ! xSource.is())
78*b1cdbd2cSJim Jagielski         return InterpretedData();
79*b1cdbd2cSJim Jagielski 
80*b1cdbd2cSJim Jagielski     Reference< data::XLabeledDataSequence > xCategories;
81*b1cdbd2cSJim Jagielski     Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() );
82*b1cdbd2cSJim Jagielski     const sal_Int32 nDataCount( aData.getLength());
83*b1cdbd2cSJim Jagielski 
84*b1cdbd2cSJim Jagielski     // sub-type properties
85*b1cdbd2cSJim Jagielski     const StockChartTypeTemplate::StockVariant eVar( GetStockVariant());
86*b1cdbd2cSJim Jagielski     const bool bHasOpenValues (( eVar == StockChartTypeTemplate::OPEN_LOW_HI_CLOSE ) ||
87*b1cdbd2cSJim Jagielski                                ( eVar == StockChartTypeTemplate::VOL_OPEN_LOW_HI_CLOSE ));
88*b1cdbd2cSJim Jagielski     const bool bHasVolume (( eVar == StockChartTypeTemplate::VOL_LOW_HI_CLOSE ) ||
89*b1cdbd2cSJim Jagielski                            ( eVar == StockChartTypeTemplate::VOL_OPEN_LOW_HI_CLOSE ));
90*b1cdbd2cSJim Jagielski     const bool bHasCategories( HasCategories( rArguments, aData ));
91*b1cdbd2cSJim Jagielski 
92*b1cdbd2cSJim Jagielski     // necessary roles for "full series"
93*b1cdbd2cSJim Jagielski     // low/high/close
94*b1cdbd2cSJim Jagielski     sal_Int32 nNumberOfNecessarySequences( 3 );
95*b1cdbd2cSJim Jagielski     if( bHasOpenValues )
96*b1cdbd2cSJim Jagielski         ++nNumberOfNecessarySequences;
97*b1cdbd2cSJim Jagielski     if( bHasVolume )
98*b1cdbd2cSJim Jagielski         ++nNumberOfNecessarySequences;
99*b1cdbd2cSJim Jagielski 
100*b1cdbd2cSJim Jagielski     // calculate number of full series (nNumOfFullSeries) and the number of remaining
101*b1cdbd2cSJim Jagielski     // sequences used for additional "incomplete series" (nRemaining)
102*b1cdbd2cSJim Jagielski     sal_Int32 nNumOfFullSeries( 0 );
103*b1cdbd2cSJim Jagielski     sal_Int32 nRemaining( 0 );
104*b1cdbd2cSJim Jagielski     {
105*b1cdbd2cSJim Jagielski         sal_Int32 nAvailableSequences( nDataCount );
106*b1cdbd2cSJim Jagielski         if( bHasCategories )
107*b1cdbd2cSJim Jagielski             --nAvailableSequences;
108*b1cdbd2cSJim Jagielski         nNumOfFullSeries = nAvailableSequences / nNumberOfNecessarySequences;
109*b1cdbd2cSJim Jagielski         nRemaining = nAvailableSequences % nNumberOfNecessarySequences;
110*b1cdbd2cSJim Jagielski     }
111*b1cdbd2cSJim Jagielski     sal_Int32 nCandleStickSeries = nNumOfFullSeries;
112*b1cdbd2cSJim Jagielski     sal_Int32 nVolumeSeries = nNumOfFullSeries;
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski     sal_Int32 nNumberOfGroups( bHasVolume ? 2 : 1 );
115*b1cdbd2cSJim Jagielski     // sequences of data::XLabeledDataSequence per series per group
116*b1cdbd2cSJim Jagielski     Sequence< Sequence< Sequence< Reference< data::XLabeledDataSequence > > > > aSequences( nNumberOfGroups );
117*b1cdbd2cSJim Jagielski     sal_Int32 nBarGroupIndex( 0 );
118*b1cdbd2cSJim Jagielski     sal_Int32 nCandleStickGroupIndex( nNumberOfGroups - 1 );
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski     // allocate space for labeled sequences
121*b1cdbd2cSJim Jagielski     if( nRemaining > 0  )
122*b1cdbd2cSJim Jagielski         ++nCandleStickSeries;
123*b1cdbd2cSJim Jagielski     aSequences[nCandleStickGroupIndex].realloc( nCandleStickSeries );
124*b1cdbd2cSJim Jagielski     if( bHasVolume )
125*b1cdbd2cSJim Jagielski     {
126*b1cdbd2cSJim Jagielski         // if there are remaining sequences, the first one is taken for
127*b1cdbd2cSJim Jagielski         // additional close values, the second one is taken as volume, if volume
128*b1cdbd2cSJim Jagielski         // is used
129*b1cdbd2cSJim Jagielski         if( nRemaining > 1 )
130*b1cdbd2cSJim Jagielski             ++nVolumeSeries;
131*b1cdbd2cSJim Jagielski         aSequences[nBarGroupIndex].realloc( nVolumeSeries );
132*b1cdbd2cSJim Jagielski     }
133*b1cdbd2cSJim Jagielski 
134*b1cdbd2cSJim Jagielski 
135*b1cdbd2cSJim Jagielski     // create data
136*b1cdbd2cSJim Jagielski     sal_Int32 nSourceIndex = 0;   // index into aData sequence
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski     // 1. categories
139*b1cdbd2cSJim Jagielski     if( bHasCategories )
140*b1cdbd2cSJim Jagielski     {
141*b1cdbd2cSJim Jagielski         xCategories.set( aData[nSourceIndex] );
142*b1cdbd2cSJim Jagielski         ++nSourceIndex;
143*b1cdbd2cSJim Jagielski     }
144*b1cdbd2cSJim Jagielski 
145*b1cdbd2cSJim Jagielski     // 2. create "full" series
146*b1cdbd2cSJim Jagielski     for( sal_Int32 nLabeledSeqIdx=0; nLabeledSeqIdx<nNumOfFullSeries; ++nLabeledSeqIdx )
147*b1cdbd2cSJim Jagielski     {
148*b1cdbd2cSJim Jagielski         // bar
149*b1cdbd2cSJim Jagielski         if( bHasVolume )
150*b1cdbd2cSJim Jagielski         {
151*b1cdbd2cSJim Jagielski             aSequences[nBarGroupIndex][nLabeledSeqIdx].realloc( 1 );
152*b1cdbd2cSJim Jagielski             aSequences[nBarGroupIndex][nLabeledSeqIdx][0].set( aData[nSourceIndex] );
153*b1cdbd2cSJim Jagielski             if( aData[nSourceIndex].is())
154*b1cdbd2cSJim Jagielski                 SetRole( aData[nSourceIndex]->getValues(), C2U("values-y"));
155*b1cdbd2cSJim Jagielski             ++nSourceIndex;
156*b1cdbd2cSJim Jagielski         }
157*b1cdbd2cSJim Jagielski 
158*b1cdbd2cSJim Jagielski         sal_Int32 nSeqIdx = 0;
159*b1cdbd2cSJim Jagielski         if( bHasOpenValues )
160*b1cdbd2cSJim Jagielski         {
161*b1cdbd2cSJim Jagielski             aSequences[nCandleStickGroupIndex][nLabeledSeqIdx].realloc( 4 );
162*b1cdbd2cSJim Jagielski             aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] );
163*b1cdbd2cSJim Jagielski             if( aData[nSourceIndex].is())
164*b1cdbd2cSJim Jagielski                 SetRole( aData[nSourceIndex]->getValues(), C2U("values-first"));
165*b1cdbd2cSJim Jagielski             ++nSourceIndex, ++nSeqIdx;
166*b1cdbd2cSJim Jagielski         }
167*b1cdbd2cSJim Jagielski         else
168*b1cdbd2cSJim Jagielski             aSequences[nCandleStickGroupIndex][nLabeledSeqIdx].realloc( 3 );
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski         aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] );
171*b1cdbd2cSJim Jagielski         if( aData[nSourceIndex].is())
172*b1cdbd2cSJim Jagielski             SetRole( aData[nSourceIndex]->getValues(), C2U("values-min"));
173*b1cdbd2cSJim Jagielski         ++nSourceIndex, ++nSeqIdx;
174*b1cdbd2cSJim Jagielski 
175*b1cdbd2cSJim Jagielski         aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] );
176*b1cdbd2cSJim Jagielski         if( aData[nSourceIndex].is())
177*b1cdbd2cSJim Jagielski             SetRole( aData[nSourceIndex]->getValues(), C2U("values-max"));
178*b1cdbd2cSJim Jagielski         ++nSourceIndex, ++nSeqIdx;
179*b1cdbd2cSJim Jagielski 
180*b1cdbd2cSJim Jagielski         aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] );
181*b1cdbd2cSJim Jagielski         if( aData[nSourceIndex].is())
182*b1cdbd2cSJim Jagielski             SetRole( aData[nSourceIndex]->getValues(), C2U("values-last"));
183*b1cdbd2cSJim Jagielski         ++nSourceIndex, ++nSeqIdx;
184*b1cdbd2cSJim Jagielski     }
185*b1cdbd2cSJim Jagielski 
186*b1cdbd2cSJim Jagielski     // 3. create series with remaining sequences
187*b1cdbd2cSJim Jagielski     if( bHasVolume && nRemaining > 1 )
188*b1cdbd2cSJim Jagielski     {
189*b1cdbd2cSJim Jagielski         OSL_ASSERT( nVolumeSeries > nNumOfFullSeries );
190*b1cdbd2cSJim Jagielski         aSequences[nBarGroupIndex][nVolumeSeries - 1].realloc( 1 );
191*b1cdbd2cSJim Jagielski         OSL_ASSERT( nDataCount > nSourceIndex );
192*b1cdbd2cSJim Jagielski         if( aData[nSourceIndex].is())
193*b1cdbd2cSJim Jagielski             SetRole( aData[nSourceIndex]->getValues(), C2U("values-y"));
194*b1cdbd2cSJim Jagielski         aSequences[nBarGroupIndex][nVolumeSeries - 1][0].set( aData[nSourceIndex] );
195*b1cdbd2cSJim Jagielski         ++nSourceIndex;
196*b1cdbd2cSJim Jagielski         --nRemaining;
197*b1cdbd2cSJim Jagielski         OSL_ENSURE( nRemaining, "additional bar should only be used if there is at least one more sequence for a candle stick" );
198*b1cdbd2cSJim Jagielski     }
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski     // candle-stick
201*b1cdbd2cSJim Jagielski     if( nRemaining > 0 )
202*b1cdbd2cSJim Jagielski     {
203*b1cdbd2cSJim Jagielski         OSL_ASSERT( nCandleStickSeries > nNumOfFullSeries );
204*b1cdbd2cSJim Jagielski         const sal_Int32 nSeriesIndex = nCandleStickSeries - 1;
205*b1cdbd2cSJim Jagielski         aSequences[nCandleStickGroupIndex][nSeriesIndex].realloc( nRemaining );
206*b1cdbd2cSJim Jagielski         OSL_ASSERT( nDataCount > nSourceIndex );
207*b1cdbd2cSJim Jagielski 
208*b1cdbd2cSJim Jagielski         // 1. low
209*b1cdbd2cSJim Jagielski         sal_Int32 nSeqIdx( 0 );
210*b1cdbd2cSJim Jagielski         aSequences[nCandleStickGroupIndex][nSeriesIndex][nSeqIdx].set( aData[nSourceIndex] );
211*b1cdbd2cSJim Jagielski         if( aData[nSourceIndex].is())
212*b1cdbd2cSJim Jagielski             SetRole( aData[nSourceIndex]->getValues(), C2U("values-min"));
213*b1cdbd2cSJim Jagielski         ++nSourceIndex, ++nSeqIdx;
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski         // 2. high
216*b1cdbd2cSJim Jagielski         if( nSeqIdx < nRemaining )
217*b1cdbd2cSJim Jagielski         {
218*b1cdbd2cSJim Jagielski             aSequences[nCandleStickGroupIndex][nSeriesIndex][nSeqIdx].set( aData[nSourceIndex] );
219*b1cdbd2cSJim Jagielski             if( aData[nSourceIndex].is())
220*b1cdbd2cSJim Jagielski                 SetRole( aData[nSourceIndex]->getValues(), C2U("values-max"));
221*b1cdbd2cSJim Jagielski             ++nSourceIndex, ++nSeqIdx;
222*b1cdbd2cSJim Jagielski         }
223*b1cdbd2cSJim Jagielski 
224*b1cdbd2cSJim Jagielski         // 3. close
225*b1cdbd2cSJim Jagielski         OSL_ENSURE( bHasOpenValues || nSeqIdx >= nRemaining, "could have created full series" );
226*b1cdbd2cSJim Jagielski         if( nSeqIdx < nRemaining )
227*b1cdbd2cSJim Jagielski         {
228*b1cdbd2cSJim Jagielski             aSequences[nCandleStickGroupIndex][nSeriesIndex][nSeqIdx].set( aData[nSourceIndex] );
229*b1cdbd2cSJim Jagielski             if( aData[nSourceIndex].is())
230*b1cdbd2cSJim Jagielski                 SetRole( aData[nSourceIndex]->getValues(), C2U("values-last"));
231*b1cdbd2cSJim Jagielski             ++nSourceIndex, ++nSeqIdx;
232*b1cdbd2cSJim Jagielski         }
233*b1cdbd2cSJim Jagielski 
234*b1cdbd2cSJim Jagielski         // 4. open
235*b1cdbd2cSJim Jagielski         OSL_ENSURE( nSeqIdx >= nRemaining, "could have created full series" );
236*b1cdbd2cSJim Jagielski     }
237*b1cdbd2cSJim Jagielski 
238*b1cdbd2cSJim Jagielski     // create DataSeries
239*b1cdbd2cSJim Jagielski     Sequence< Sequence< Reference< XDataSeries > > > aResultSeries( nNumberOfGroups );
240*b1cdbd2cSJim Jagielski     sal_Int32 nGroupIndex, nReUsedSeriesIdx = 0;
241*b1cdbd2cSJim Jagielski     for( nGroupIndex=0; nGroupIndex<nNumberOfGroups; ++nGroupIndex )
242*b1cdbd2cSJim Jagielski     {
243*b1cdbd2cSJim Jagielski         const sal_Int32 nNumSeriesData = aSequences[nGroupIndex].getLength();
244*b1cdbd2cSJim Jagielski         aResultSeries[nGroupIndex].realloc( nNumSeriesData );
245*b1cdbd2cSJim Jagielski         for( sal_Int32 nSeriesIdx = 0; nSeriesIdx < nNumSeriesData; ++nSeriesIdx, ++nReUsedSeriesIdx )
246*b1cdbd2cSJim Jagielski         {
247*b1cdbd2cSJim Jagielski             try
248*b1cdbd2cSJim Jagielski             {
249*b1cdbd2cSJim Jagielski                 Reference< XDataSeries > xSeries;
250*b1cdbd2cSJim Jagielski                 if( nReUsedSeriesIdx < rSeriesToReUse.getLength())
251*b1cdbd2cSJim Jagielski                     xSeries.set( rSeriesToReUse[nReUsedSeriesIdx] );
252*b1cdbd2cSJim Jagielski                 else
253*b1cdbd2cSJim Jagielski                     xSeries.set( new DataSeries( GetComponentContext() ) );
254*b1cdbd2cSJim Jagielski                 OSL_ASSERT( xSeries.is() );
255*b1cdbd2cSJim Jagielski                 Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY_THROW );
256*b1cdbd2cSJim Jagielski                 OSL_ASSERT( xSink.is() );
257*b1cdbd2cSJim Jagielski                 xSink->setData( aSequences[nGroupIndex][nSeriesIdx] );
258*b1cdbd2cSJim Jagielski                 aResultSeries[nGroupIndex][nSeriesIdx].set( xSeries );
259*b1cdbd2cSJim Jagielski             }
260*b1cdbd2cSJim Jagielski             catch( uno::Exception & ex )
261*b1cdbd2cSJim Jagielski             {
262*b1cdbd2cSJim Jagielski                 ASSERT_EXCEPTION( ex );
263*b1cdbd2cSJim Jagielski             }
264*b1cdbd2cSJim Jagielski         }
265*b1cdbd2cSJim Jagielski     }
266*b1cdbd2cSJim Jagielski 
267*b1cdbd2cSJim Jagielski     return InterpretedData( aResultSeries, xCategories );
268*b1cdbd2cSJim Jagielski }
269*b1cdbd2cSJim Jagielski 
270*b1cdbd2cSJim Jagielski // criterion: there must be two groups for stock-charts with volume and all
271*b1cdbd2cSJim Jagielski // series must have the correct number of data::XLabeledDataSequences
272*b1cdbd2cSJim Jagielski 
273*b1cdbd2cSJim Jagielski // todo: skip first criterion? (to allow easy switch from stock-chart without
274*b1cdbd2cSJim Jagielski // volume to one with volume)
isDataCompatible(const InterpretedData & aInterpretedData)275*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL StockDataInterpreter::isDataCompatible(
276*b1cdbd2cSJim Jagielski     const InterpretedData& aInterpretedData )
277*b1cdbd2cSJim Jagielski     throw (uno::RuntimeException)
278*b1cdbd2cSJim Jagielski {
279*b1cdbd2cSJim Jagielski     // high/low/close
280*b1cdbd2cSJim Jagielski     sal_Int32 nNumberOfNecessarySequences = 3;
281*b1cdbd2cSJim Jagielski     // open
282*b1cdbd2cSJim Jagielski     StockChartTypeTemplate::StockVariant eVar( GetStockVariant());
283*b1cdbd2cSJim Jagielski     if( ( eVar == StockChartTypeTemplate::OPEN_LOW_HI_CLOSE ) ||
284*b1cdbd2cSJim Jagielski         ( eVar == StockChartTypeTemplate::VOL_OPEN_LOW_HI_CLOSE ))
285*b1cdbd2cSJim Jagielski         ++nNumberOfNecessarySequences;
286*b1cdbd2cSJim Jagielski     // volume
287*b1cdbd2cSJim Jagielski     bool bHasVolume = (( eVar == StockChartTypeTemplate::VOL_LOW_HI_CLOSE ) ||
288*b1cdbd2cSJim Jagielski                        ( eVar == StockChartTypeTemplate::VOL_OPEN_LOW_HI_CLOSE ));
289*b1cdbd2cSJim Jagielski 
290*b1cdbd2cSJim Jagielski     // 1. correct number of sub-types
291*b1cdbd2cSJim Jagielski     if( aInterpretedData.Series.getLength() < (bHasVolume ? 2 : 1 ))
292*b1cdbd2cSJim Jagielski         return sal_False;
293*b1cdbd2cSJim Jagielski 
294*b1cdbd2cSJim Jagielski     // 2. a. volume -- use default check
295*b1cdbd2cSJim Jagielski     if( bHasVolume )
296*b1cdbd2cSJim Jagielski     {
297*b1cdbd2cSJim Jagielski         if( ! DataInterpreter::isDataCompatible(
298*b1cdbd2cSJim Jagielski                 InterpretedData( Sequence< Sequence< Reference< XDataSeries > > >(
299*b1cdbd2cSJim Jagielski                                      aInterpretedData.Series.getConstArray(), 1 ),
300*b1cdbd2cSJim Jagielski                                  aInterpretedData.Categories )))
301*b1cdbd2cSJim Jagielski             return sal_False;
302*b1cdbd2cSJim Jagielski     }
303*b1cdbd2cSJim Jagielski 
304*b1cdbd2cSJim Jagielski     // 2. b. candlestick
305*b1cdbd2cSJim Jagielski     {
306*b1cdbd2cSJim Jagielski         OSL_ASSERT( aInterpretedData.Series.getLength() > (bHasVolume ? 1 : 0));
307*b1cdbd2cSJim Jagielski         Sequence< Reference< XDataSeries > > aSeries( aInterpretedData.Series[(bHasVolume ? 1 : 0)] );
308*b1cdbd2cSJim Jagielski         if(!aSeries.getLength())
309*b1cdbd2cSJim Jagielski             return sal_False;
310*b1cdbd2cSJim Jagielski         for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
311*b1cdbd2cSJim Jagielski         {
312*b1cdbd2cSJim Jagielski             try
313*b1cdbd2cSJim Jagielski             {
314*b1cdbd2cSJim Jagielski                 Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW );
315*b1cdbd2cSJim Jagielski                 Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences());
316*b1cdbd2cSJim Jagielski                 if( aSeq.getLength() != nNumberOfNecessarySequences )
317*b1cdbd2cSJim Jagielski                     return sal_False;
318*b1cdbd2cSJim Jagielski             }
319*b1cdbd2cSJim Jagielski             catch( uno::Exception & ex )
320*b1cdbd2cSJim Jagielski             {
321*b1cdbd2cSJim Jagielski                 ASSERT_EXCEPTION( ex );
322*b1cdbd2cSJim Jagielski             }
323*b1cdbd2cSJim Jagielski         }
324*b1cdbd2cSJim Jagielski     }
325*b1cdbd2cSJim Jagielski 
326*b1cdbd2cSJim Jagielski     // 2. c. additional series
327*b1cdbd2cSJim Jagielski     // ignore
328*b1cdbd2cSJim Jagielski 
329*b1cdbd2cSJim Jagielski     return sal_True;
330*b1cdbd2cSJim Jagielski }
331*b1cdbd2cSJim Jagielski 
reinterpretDataSeries(const InterpretedData & aInterpretedData)332*b1cdbd2cSJim Jagielski InterpretedData SAL_CALL StockDataInterpreter::reinterpretDataSeries(
333*b1cdbd2cSJim Jagielski     const InterpretedData& aInterpretedData )
334*b1cdbd2cSJim Jagielski     throw (uno::RuntimeException)
335*b1cdbd2cSJim Jagielski {
336*b1cdbd2cSJim Jagielski     // prerequisite: StockDataInterpreter::isDataCompatible() returned true
337*b1cdbd2cSJim Jagielski     return aInterpretedData;
338*b1cdbd2cSJim Jagielski }
339*b1cdbd2cSJim Jagielski 
340*b1cdbd2cSJim Jagielski } // namespace chart
341