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 "CachedDataSequence.hxx"
28 #include "macros.hxx"
29 #include "PropertyHelper.hxx"
30 #include "ContainerHelper.hxx"
31 #include "CommonFunctors.hxx"
32 #include "ModifyListenerHelper.hxx"
33 
34 #include <comphelper/sequenceashashmap.hxx>
35 
36 #include <algorithm>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <rtl/math.hxx>
39 
40 using namespace ::com::sun::star;
41 using namespace ::chart::ContainerHelper;
42 
43 using ::com::sun::star::uno::Sequence;
44 using ::com::sun::star::uno::Reference;
45 using ::com::sun::star::uno::Any;
46 using ::rtl::OUString;
47 using ::osl::MutexGuard;
48 
49 // necessary for MS compiler
50 using ::comphelper::OPropertyContainer;
51 using ::comphelper::OMutexAndBroadcastHelper;
52 using ::comphelper::OPropertyArrayUsageHelper;
53 using ::chart::impl::CachedDataSequence_Base;
54 
55 namespace
56 {
57 static const OUString lcl_aServiceName(
58     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.CachedDataSequence" ));
59 
60 enum
61 {
62 //     PROP_SOURCE_IDENTIFIER,
63     PROP_NUMBERFORMAT_KEY,
64     PROP_PROPOSED_ROLE
65 };
66 }  // anonymous namespace
67 
68 
69 // ____________________
70 namespace chart
71 {
72 
CachedDataSequence()73 CachedDataSequence::CachedDataSequence()
74         : OPropertyContainer( GetBroadcastHelper()),
75           CachedDataSequence_Base( GetMutex()),
76           m_eCurrentDataType( NUMERICAL ),
77           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
78 {
79     registerProperties();
80 }
CachedDataSequence(const Reference<uno::XComponentContext> &)81 CachedDataSequence::CachedDataSequence( const Reference< uno::XComponentContext > & /*xContext*/ )
82         : OPropertyContainer( GetBroadcastHelper()),
83           CachedDataSequence_Base( GetMutex()),
84           m_eCurrentDataType( MIXED ),
85           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder( ))
86 {
87     registerProperties();
88 }
89 
CachedDataSequence(const OUString & rSingleText)90 CachedDataSequence::CachedDataSequence( const OUString & rSingleText )
91         : OPropertyContainer( GetBroadcastHelper()),
92           CachedDataSequence_Base( GetMutex()),
93           m_eCurrentDataType( TEXTUAL ),
94           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
95 {
96     m_aTextualSequence.realloc(1);
97     m_aTextualSequence[0] = rSingleText;
98     registerProperties();
99 }
100 
CachedDataSequence(const CachedDataSequence & rSource)101 CachedDataSequence::CachedDataSequence( const CachedDataSequence & rSource )
102         : OMutexAndBroadcastHelper(),
103           OPropertyContainer( GetBroadcastHelper()),
104           OPropertyArrayUsageHelper< CachedDataSequence >(),
105           CachedDataSequence_Base( GetMutex()),
106           m_nNumberFormatKey( rSource.m_nNumberFormatKey ),
107           m_sRole( rSource.m_sRole ),
108           m_eCurrentDataType( rSource.m_eCurrentDataType ),
109           m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
110 {
111     switch( m_eCurrentDataType )
112     {
113         case TEXTUAL:
114             m_aTextualSequence = rSource.m_aTextualSequence;
115             break;
116         case NUMERICAL:
117             m_aNumericalSequence = rSource.m_aNumericalSequence;
118             break;
119         case MIXED:
120             m_aMixedSequence = rSource.m_aMixedSequence;
121             break;
122     }
123 
124     registerProperties();
125 }
126 
~CachedDataSequence()127 CachedDataSequence::~CachedDataSequence()
128 {}
129 
registerProperties()130 void CachedDataSequence::registerProperties()
131 {
132     registerProperty( C2U( "NumberFormatKey" ),
133                       PROP_NUMBERFORMAT_KEY,
134                       0,   // PropertyAttributes
135                       & m_nNumberFormatKey,
136                       ::getCppuType( & m_nNumberFormatKey ) );
137 
138     registerProperty( C2U( "Role" ),
139                       PROP_PROPOSED_ROLE,
140                       0,   // PropertyAttributes
141                       & m_sRole,
142                       ::getCppuType( & m_sRole ) );
143 }
144 
Impl_getNumericalData() const145 Sequence< double > CachedDataSequence::Impl_getNumericalData() const
146 {
147     if( m_eCurrentDataType == NUMERICAL )
148         return m_aNumericalSequence;
149 
150     sal_Int32 nSize = ( m_eCurrentDataType == TEXTUAL )
151         ? m_aTextualSequence.getLength()
152         : m_aMixedSequence.getLength();
153 
154     Sequence< double > aResult( nSize );
155     double * pResultArray = aResult.getArray();
156 
157     if( m_eCurrentDataType == TEXTUAL )
158     {
159         const OUString * pTextArray = m_aTextualSequence.getConstArray();
160         ::std::transform( pTextArray, pTextArray + nSize,
161                           pResultArray,
162                           CommonFunctors::OUStringToDouble() );
163     }
164     else
165     {
166         OSL_ASSERT( m_eCurrentDataType == MIXED );
167         const Any * pMixedArray = m_aMixedSequence.getConstArray();
168         ::std::transform( pMixedArray, pMixedArray + nSize,
169                           pResultArray,
170                           CommonFunctors::AnyToDouble() );
171     }
172     return aResult;
173 }
174 
Impl_getTextualData() const175 Sequence< OUString > CachedDataSequence::Impl_getTextualData() const
176 {
177     if( m_eCurrentDataType == TEXTUAL )
178         return m_aTextualSequence;
179 
180     sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL )
181         ? m_aNumericalSequence.getLength()
182         : m_aMixedSequence.getLength();
183 
184     Sequence< OUString > aResult( nSize );
185     OUString * pResultArray = aResult.getArray();
186 
187     if( m_eCurrentDataType == NUMERICAL )
188     {
189         const double * pTextArray = m_aNumericalSequence.getConstArray();
190         ::std::transform( pTextArray, pTextArray + nSize,
191                           pResultArray,
192                           CommonFunctors::DoubleToOUString() );
193     }
194     else
195     {
196         OSL_ASSERT( m_eCurrentDataType == MIXED );
197         const Any * pMixedArray = m_aMixedSequence.getConstArray();
198         ::std::transform( pMixedArray, pMixedArray + nSize,
199                           pResultArray,
200                           CommonFunctors::AnyToString() );
201     }
202 
203     return aResult;
204 }
205 
Impl_getMixedData() const206 Sequence< Any > CachedDataSequence::Impl_getMixedData() const
207 {
208     if( m_eCurrentDataType == MIXED )
209         return m_aMixedSequence;
210 
211     sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL )
212         ? m_aNumericalSequence.getLength()
213         : m_aTextualSequence.getLength();
214 
215     Sequence< Any > aResult( nSize );
216     Any * pResultArray = aResult.getArray();
217 
218     if( m_eCurrentDataType == NUMERICAL )
219     {
220         const double * pTextArray = m_aNumericalSequence.getConstArray();
221         ::std::transform( pTextArray, pTextArray + nSize,
222                           pResultArray,
223                           CommonFunctors::makeAny< double >() );
224     }
225     else
226     {
227         OSL_ASSERT( m_eCurrentDataType == TEXTUAL );
228         const OUString * pMixedArray = m_aTextualSequence.getConstArray();
229         ::std::transform( pMixedArray, pMixedArray + nSize,
230                           pResultArray,
231                           CommonFunctors::makeAny< OUString >() );
232     }
233 
234     return aResult;
235 }
236 
237 // ================================================================================
238 
getSupportedServiceNames_Static()239 Sequence< OUString > CachedDataSequence::getSupportedServiceNames_Static()
240 {
241     Sequence< OUString > aServices( 4 );
242     aServices[ 0 ] = lcl_aServiceName;
243     aServices[ 1 ] = C2U( "com.sun.star.chart2.data.DataSequence" );
244     aServices[ 2 ] = C2U( "com.sun.star.chart2.data.NumericalDataSequence" );
245     aServices[ 3 ] = C2U( "com.sun.star.chart2.data.TextualDataSequence" );
246     return aServices;
247 }
248 
IMPLEMENT_FORWARD_XINTERFACE2(CachedDataSequence,CachedDataSequence_Base,OPropertyContainer)249 IMPLEMENT_FORWARD_XINTERFACE2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer )
250 IMPLEMENT_FORWARD_XTYPEPROVIDER2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer )
251 
252 // ____ XPropertySet ____
253 Reference< beans::XPropertySetInfo > SAL_CALL CachedDataSequence::getPropertySetInfo()
254     throw(uno::RuntimeException)
255 {
256     return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) );
257 }
258 
259 // ____ ::comphelper::OPropertySetHelper ____
260 // __________________________________________
getInfoHelper()261 ::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper()
262 {
263 	return *getArrayHelper();
264 }
265 
266 // ____ ::comphelper::OPropertyArrayHelper ____
267 // ____________________________________________
createArrayHelper() const268 ::cppu::IPropertyArrayHelper* CachedDataSequence::createArrayHelper() const
269 {
270 	Sequence< beans::Property > aProps;
271     // describes all properties which have been registered in the ctor
272 	describeProperties( aProps );
273 
274 	return new ::cppu::OPropertyArrayHelper( aProps );
275 }
276 
277 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL(CachedDataSequence,lcl_aServiceName)278 APPHELPER_XSERVICEINFO_IMPL( CachedDataSequence, lcl_aServiceName )
279 
280 // ================================================================================
281 
282 // ________ XNumericalDataSequence ________
283 Sequence< double > SAL_CALL CachedDataSequence::getNumericalData()
284     throw (uno::RuntimeException)
285 {
286     // /--
287     MutexGuard aGuard( GetMutex() );
288 
289     if( m_eCurrentDataType == NUMERICAL )
290         return m_aNumericalSequence;
291     else
292         return Impl_getNumericalData();
293     // \--
294 }
295 
296 // ________ XTextualDataSequence ________
getTextualData()297 Sequence< OUString > SAL_CALL CachedDataSequence::getTextualData()
298     throw (uno::RuntimeException)
299 {
300     // /--
301     MutexGuard aGuard( GetMutex() );
302 
303     if( m_eCurrentDataType == TEXTUAL )
304         return m_aTextualSequence;
305     else
306         return Impl_getTextualData();
307     // \--
308 }
309 
310 // void SAL_CALL CachedDataSequence::setTextualData( const Sequence< OUString >& aData )
311 //     throw (uno::RuntimeException)
312 // {
313 //     // /--
314 //     MutexGuard aGuard( GetMutex() );
315 //     Impl_setTextualData( aData );
316 //     // \--
317 // }
318 
319 // ________ XDataSequence  ________
getData()320 Sequence< Any > SAL_CALL CachedDataSequence::getData()
321     throw (uno::RuntimeException)
322 {
323     // /--
324     MutexGuard aGuard( GetMutex() );
325     return Impl_getMixedData();
326     // \--
327 }
328 
getSourceRangeRepresentation()329 OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation()
330     throw (uno::RuntimeException)
331 {
332     return m_sRole;
333 }
334 
generateLabel(chart2::data::LabelOrigin)335 Sequence< OUString > SAL_CALL CachedDataSequence::generateLabel( chart2::data::LabelOrigin  /*eLabelOrigin*/ )
336     throw (uno::RuntimeException)
337 {
338     // return empty label, as we have no range representaions to determine something useful
339     return Sequence< OUString >();
340 }
341 
getNumberFormatKeyByIndex(::sal_Int32)342 ::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
343     throw (lang::IndexOutOfBoundsException,
344            uno::RuntimeException)
345 {
346     return 0;
347 }
348 
createClone()349 Reference< util::XCloneable > SAL_CALL CachedDataSequence::createClone()
350     throw (uno::RuntimeException)
351 {
352     CachedDataSequence * pNewSeq = new CachedDataSequence( *this );
353 
354     return Reference< util::XCloneable >( pNewSeq );
355 }
356 
addModifyListener(const Reference<util::XModifyListener> & aListener)357 void SAL_CALL CachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener )
358     throw (uno::RuntimeException)
359 {
360     try
361     {
362         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
363         xBroadcaster->addModifyListener( aListener );
364     }
365     catch( const uno::Exception & ex )
366     {
367         ASSERT_EXCEPTION( ex );
368     }
369 }
370 
removeModifyListener(const Reference<util::XModifyListener> & aListener)371 void SAL_CALL CachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener )
372     throw (uno::RuntimeException)
373 {
374     try
375     {
376         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
377         xBroadcaster->removeModifyListener( aListener );
378     }
379     catch( const uno::Exception & ex )
380     {
381         ASSERT_EXCEPTION( ex );
382     }
383 }
384 
385 // lang::XInitialization:
initialize(const uno::Sequence<uno::Any> & _aArguments)386 void SAL_CALL CachedDataSequence::initialize(const uno::Sequence< uno::Any > & _aArguments) throw (uno::RuntimeException, uno::Exception)
387 {
388     ::comphelper::SequenceAsHashMap aMap(_aArguments);
389     m_aNumericalSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aNumericalSequence);
390     if ( m_aNumericalSequence.getLength() )
391         m_eCurrentDataType = NUMERICAL;
392     else
393     {
394         m_aTextualSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aTextualSequence);
395         if ( m_aTextualSequence.getLength() )
396             m_eCurrentDataType = TEXTUAL;
397         else
398         {
399             m_aMixedSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aMixedSequence);
400             if ( m_aMixedSequence.getLength() )
401                 m_eCurrentDataType = MIXED;
402         }
403     }
404 }
405 }  // namespace chart
406