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 73 CachedDataSequence::CachedDataSequence() 74 : OPropertyContainer( GetBroadcastHelper()), 75 CachedDataSequence_Base( GetMutex()), 76 m_eCurrentDataType( NUMERICAL ), 77 m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) 78 { 79 registerProperties(); 80 } 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 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 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 127 CachedDataSequence::~CachedDataSequence() 128 {} 129 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 145 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 175 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 206 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 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 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 // __________________________________________ 261 ::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper() 262 { 263 return *getArrayHelper(); 264 } 265 266 // ____ ::comphelper::OPropertyArrayHelper ____ 267 // ____________________________________________ 268 ::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 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 ________ 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 ________ 320 Sequence< Any > SAL_CALL CachedDataSequence::getData() 321 throw (uno::RuntimeException) 322 { 323 // /-- 324 MutexGuard aGuard( GetMutex() ); 325 return Impl_getMixedData(); 326 // \-- 327 } 328 329 OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation() 330 throw (uno::RuntimeException) 331 { 332 return m_sRole; 333 } 334 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 342 ::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) 343 throw (lang::IndexOutOfBoundsException, 344 uno::RuntimeException) 345 { 346 return 0; 347 } 348 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 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 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: 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