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 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 { 255 return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) ); 256 } 257 258 // ____ ::comphelper::OPropertySetHelper ____ 259 // __________________________________________ 260 ::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper() 261 { 262 return *getArrayHelper(); 263 } 264 265 // ____ ::comphelper::OPropertyArrayHelper ____ 266 // ____________________________________________ 267 ::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 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 ________ 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 ________ 317 Sequence< Any > SAL_CALL CachedDataSequence::getData() 318 { 319 // /-- 320 MutexGuard aGuard( GetMutex() ); 321 return Impl_getMixedData(); 322 // \-- 323 } 324 325 OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation() 326 { 327 return m_sRole; 328 } 329 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 336 ::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) 337 { 338 return 0; 339 } 340 341 Reference< util::XCloneable > SAL_CALL CachedDataSequence::createClone() 342 { 343 CachedDataSequence * pNewSeq = new CachedDataSequence( *this ); 344 345 return Reference< util::XCloneable >( pNewSeq ); 346 } 347 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 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: 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