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_charttools.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 {
255 return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) );
256 }
257
258 // ____ ::comphelper::OPropertySetHelper ____
259 // __________________________________________
getInfoHelper()260 ::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper()
261 {
262 return *getArrayHelper();
263 }
264
265 // ____ ::comphelper::OPropertyArrayHelper ____
266 // ____________________________________________
createArrayHelper() const267 ::cppu::IPropertyArrayHelper* CachedDataSequence::createArrayHelper() const
268 {
269 Sequence< beans::Property > aProps;
270 // describes all properties which have been registered in the ctor
271 describeProperties( aProps );
272
273 return new ::cppu::OPropertyArrayHelper( aProps );
274 }
275
276 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL(CachedDataSequence,lcl_aServiceName)277 APPHELPER_XSERVICEINFO_IMPL( CachedDataSequence, lcl_aServiceName )
278
279 // ================================================================================
280
281 // ________ XNumericalDataSequence ________
282 Sequence< double > SAL_CALL CachedDataSequence::getNumericalData()
283 {
284 // /--
285 MutexGuard aGuard( GetMutex() );
286
287 if( m_eCurrentDataType == NUMERICAL )
288 return m_aNumericalSequence;
289 else
290 return Impl_getNumericalData();
291 // \--
292 }
293
294 // ________ XTextualDataSequence ________
getTextualData()295 Sequence< OUString > SAL_CALL CachedDataSequence::getTextualData()
296 {
297 // /--
298 MutexGuard aGuard( GetMutex() );
299
300 if( m_eCurrentDataType == TEXTUAL )
301 return m_aTextualSequence;
302 else
303 return Impl_getTextualData();
304 // \--
305 }
306
307 // void SAL_CALL CachedDataSequence::setTextualData( const Sequence< OUString >& aData )
308 // throw (uno::RuntimeException)
309 // {
310 // // /--
311 // MutexGuard aGuard( GetMutex() );
312 // Impl_setTextualData( aData );
313 // // \--
314 // }
315
316 // ________ XDataSequence ________
getData()317 Sequence< Any > SAL_CALL CachedDataSequence::getData()
318 {
319 // /--
320 MutexGuard aGuard( GetMutex() );
321 return Impl_getMixedData();
322 // \--
323 }
324
getSourceRangeRepresentation()325 OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation()
326 {
327 return m_sRole;
328 }
329
generateLabel(chart2::data::LabelOrigin)330 Sequence< OUString > SAL_CALL CachedDataSequence::generateLabel( chart2::data::LabelOrigin /*eLabelOrigin*/ )
331 {
332 // return empty label, as we have no range representaions to determine something useful
333 return Sequence< OUString >();
334 }
335
getNumberFormatKeyByIndex(::sal_Int32)336 ::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
337 {
338 return 0;
339 }
340
createClone()341 Reference< util::XCloneable > SAL_CALL CachedDataSequence::createClone()
342 {
343 CachedDataSequence * pNewSeq = new CachedDataSequence( *this );
344
345 return Reference< util::XCloneable >( pNewSeq );
346 }
347
addModifyListener(const Reference<util::XModifyListener> & aListener)348 void SAL_CALL CachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener )
349 {
350 try
351 {
352 Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
353 xBroadcaster->addModifyListener( aListener );
354 }
355 catch( const uno::Exception & ex )
356 {
357 ASSERT_EXCEPTION( ex );
358 }
359 }
360
removeModifyListener(const Reference<util::XModifyListener> & aListener)361 void SAL_CALL CachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener )
362 {
363 try
364 {
365 Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
366 xBroadcaster->removeModifyListener( aListener );
367 }
368 catch( const uno::Exception & ex )
369 {
370 ASSERT_EXCEPTION( ex );
371 }
372 }
373
374 // lang::XInitialization:
initialize(const uno::Sequence<uno::Any> & _aArguments)375 void SAL_CALL CachedDataSequence::initialize(const uno::Sequence< uno::Any > & _aArguments)
376 {
377 ::comphelper::SequenceAsHashMap aMap(_aArguments);
378 m_aNumericalSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aNumericalSequence);
379 if ( m_aNumericalSequence.getLength() )
380 m_eCurrentDataType = NUMERICAL;
381 else
382 {
383 m_aTextualSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aTextualSequence);
384 if ( m_aTextualSequence.getLength() )
385 m_eCurrentDataType = TEXTUAL;
386 else
387 {
388 m_aMixedSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aMixedSequence);
389 if ( m_aMixedSequence.getLength() )
390 m_eCurrentDataType = MIXED;
391 }
392 }
393 }
394 } // namespace chart
395