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