1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 #include "precompiled_svtools.hxx" 28 29 #include "cellvalueconversion.hxx" 30 31 /** === begin UNO includes === **/ 32 #include <com/sun/star/util/XNumberFormatter.hpp> 33 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 34 #include <com/sun/star/beans/XPropertySet.hpp> 35 #include <com/sun/star/util/Date.hpp> 36 #include <com/sun/star/util/DateTime.hpp> 37 #include <com/sun/star/util/Time.hpp> 38 #include <com/sun/star/util/XNumberFormatTypes.hpp> 39 #include <com/sun/star/util/NumberFormat.hpp> 40 /** === end UNO includes === **/ 41 42 #include <comphelper/componentcontext.hxx> 43 #include <rtl/math.hxx> 44 #include <rtl/strbuf.hxx> 45 #include <tools/date.hxx> 46 #include <tools/time.hxx> 47 #include <tools/diagnose_ex.h> 48 #include <unotools/syslocale.hxx> 49 50 #include <boost/shared_ptr.hpp> 51 #include <hash_map> 52 53 //...................................................................................................................... 54 namespace svt 55 { 56 //...................................................................................................................... 57 58 /** === begin UNO using === **/ 59 using ::com::sun::star::uno::Any; 60 using ::com::sun::star::util::XNumberFormatter; 61 using ::com::sun::star::uno::UNO_QUERY_THROW; 62 using ::com::sun::star::util::XNumberFormatsSupplier; 63 using ::com::sun::star::beans::XPropertySet; 64 using ::com::sun::star::uno::UNO_SET_THROW; 65 using ::com::sun::star::uno::Exception; 66 using ::com::sun::star::util::DateTime; 67 using ::com::sun::star::uno::TypeClass; 68 using ::com::sun::star::util::XNumberFormatTypes; 69 using ::com::sun::star::uno::Reference; 70 using ::com::sun::star::uno::Sequence; 71 using ::com::sun::star::uno::makeAny; 72 using ::com::sun::star::uno::Type; 73 using ::com::sun::star::uno::TypeClass_BYTE; 74 using ::com::sun::star::uno::TypeClass_SHORT; 75 using ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT; 76 using ::com::sun::star::uno::TypeClass_LONG; 77 using ::com::sun::star::uno::TypeClass_UNSIGNED_LONG; 78 using ::com::sun::star::uno::TypeClass_HYPER; 79 /** === end UNO using === **/ 80 namespace NumberFormat = ::com::sun::star::util::NumberFormat; 81 82 typedef ::com::sun::star::util::Time UnoTime; 83 typedef ::com::sun::star::util::Date UnoDate; 84 85 //================================================================================================================== 86 //= helper 87 //================================================================================================================== 88 namespace 89 { 90 //-------------------------------------------------------------------------------------------------------------- 91 double lcl_convertDateToDays( long const i_day, long const i_month, long const i_year ) 92 { 93 long const nNullDateDays = ::Date::DateToDays( 1, 1, 1900 ); 94 long const nValueDateDays = ::Date::DateToDays( i_day, i_month, i_year ); 95 96 return nValueDateDays - nNullDateDays; 97 } 98 99 //-------------------------------------------------------------------------------------------------------------- 100 double lcl_convertTimeToDays( long const i_hours, long const i_minutes, long const i_seconds, long const i_100thSeconds ) 101 { 102 return Time( i_hours, i_minutes, i_seconds, i_100thSeconds ).GetTimeInDays(); 103 } 104 } 105 106 //================================================================================================================== 107 //= IValueNormalization 108 //================================================================================================================== 109 class SAL_NO_VTABLE IValueNormalization 110 { 111 public: 112 virtual ~IValueNormalization() { } 113 114 /** converts the given <code>Any</code> into a <code>double</code> value to be fed into a number formatter 115 */ 116 virtual double convertToDouble( Any const & i_value ) const = 0; 117 118 /** returns the format key to be used for formatting values 119 */ 120 virtual ::sal_Int32 getFormatKey() const = 0; 121 }; 122 123 typedef ::boost::shared_ptr< IValueNormalization > PValueNormalization; 124 typedef ::std::hash_map< ::rtl::OUString, PValueNormalization, ::rtl::OUStringHash > NormalizerCache; 125 126 //================================================================================================================== 127 //= CellValueConversion_Data 128 //================================================================================================================== 129 struct CellValueConversion_Data 130 { 131 ::comphelper::ComponentContext const aContext; 132 Reference< XNumberFormatter > xNumberFormatter; 133 bool bAttemptedFormatterCreation; 134 NormalizerCache aNormalizers; 135 136 CellValueConversion_Data( ::comphelper::ComponentContext const & i_context ) 137 :aContext( i_context ) 138 ,xNumberFormatter() 139 ,bAttemptedFormatterCreation( false ) 140 ,aNormalizers() 141 { 142 } 143 }; 144 145 //================================================================================================================== 146 //= StandardFormatNormalizer 147 //================================================================================================================== 148 class StandardFormatNormalizer : public IValueNormalization 149 { 150 protected: 151 StandardFormatNormalizer( Reference< XNumberFormatter > const & i_formatter, ::sal_Int32 const i_numberFormatType ) 152 :m_nFormatKey( 0 ) 153 { 154 try 155 { 156 ENSURE_OR_THROW( i_formatter.is(), "StandardFormatNormalizer: no formatter!" ); 157 Reference< XNumberFormatsSupplier > const xSupplier( i_formatter->getNumberFormatsSupplier(), UNO_SET_THROW ); 158 Reference< XNumberFormatTypes > const xTypes( xSupplier->getNumberFormats(), UNO_QUERY_THROW ); 159 m_nFormatKey = xTypes->getStandardFormat( i_numberFormatType, SvtSysLocale().GetLocale() ); 160 } 161 catch( const Exception& ) 162 { 163 DBG_UNHANDLED_EXCEPTION(); 164 } 165 } 166 167 virtual ::sal_Int32 getFormatKey() const 168 { 169 return m_nFormatKey; 170 } 171 172 private: 173 ::sal_Int32 m_nFormatKey; 174 }; 175 176 //================================================================================================================== 177 //= DoubleNormalization 178 //================================================================================================================== 179 class DoubleNormalization : public StandardFormatNormalizer 180 { 181 public: 182 DoubleNormalization( Reference< XNumberFormatter > const & i_formatter ) 183 :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER ) 184 { 185 } 186 187 virtual double convertToDouble( Any const & i_value ) const 188 { 189 double returnValue(0); 190 ::rtl::math::setNan( &returnValue ); 191 OSL_VERIFY( i_value >>= returnValue ); 192 return returnValue; 193 } 194 195 virtual ~DoubleNormalization() { } 196 }; 197 198 //================================================================================================================== 199 //= IntegerNormalization 200 //================================================================================================================== 201 class IntegerNormalization : public StandardFormatNormalizer 202 { 203 public: 204 IntegerNormalization( Reference< XNumberFormatter > const & i_formatter ) 205 :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER ) 206 { 207 } 208 209 virtual ~IntegerNormalization() {} 210 211 virtual double convertToDouble( Any const & i_value ) const 212 { 213 sal_Int64 value( 0 ); 214 OSL_VERIFY( i_value >>= value ); 215 return value; 216 } 217 }; 218 219 //================================================================================================================== 220 //= BooleanNormalization 221 //================================================================================================================== 222 class BooleanNormalization : public StandardFormatNormalizer 223 { 224 public: 225 BooleanNormalization( Reference< XNumberFormatter > const & i_formatter ) 226 :StandardFormatNormalizer( i_formatter, NumberFormat::LOGICAL ) 227 { 228 } 229 230 virtual ~BooleanNormalization() {} 231 232 virtual double convertToDouble( Any const & i_value ) const 233 { 234 bool value( false ); 235 OSL_VERIFY( i_value >>= value ); 236 return value ? 1 : 0; 237 } 238 }; 239 240 //================================================================================================================== 241 //= DateTimeNormalization 242 //================================================================================================================== 243 class DateTimeNormalization : public StandardFormatNormalizer 244 { 245 public: 246 DateTimeNormalization( Reference< XNumberFormatter > const & i_formatter ) 247 :StandardFormatNormalizer( i_formatter, NumberFormat::DATETIME ) 248 { 249 } 250 251 virtual ~DateTimeNormalization() {} 252 253 virtual double convertToDouble( Any const & i_value ) const 254 { 255 double returnValue(0); 256 ::rtl::math::setNan( &returnValue ); 257 258 // extract actual UNO value 259 DateTime aDateTimeValue; 260 ENSURE_OR_RETURN( i_value >>= aDateTimeValue, "allowed for DateTime values only", returnValue ); 261 262 // date part 263 returnValue = lcl_convertDateToDays( aDateTimeValue.Day, aDateTimeValue.Month, aDateTimeValue.Year ); 264 265 // time part 266 returnValue += lcl_convertTimeToDays( 267 aDateTimeValue.Hours, aDateTimeValue.Minutes, aDateTimeValue.Seconds, aDateTimeValue.HundredthSeconds ); 268 269 // done 270 return returnValue; 271 } 272 }; 273 274 //================================================================================================================== 275 //= DateNormalization 276 //================================================================================================================== 277 class DateNormalization : public StandardFormatNormalizer 278 { 279 public: 280 DateNormalization( Reference< XNumberFormatter > const & i_formatter ) 281 :StandardFormatNormalizer( i_formatter, NumberFormat::DATE ) 282 { 283 } 284 285 virtual ~DateNormalization() {} 286 287 virtual double convertToDouble( Any const & i_value ) const 288 { 289 double returnValue(0); 290 ::rtl::math::setNan( &returnValue ); 291 292 // extract 293 UnoDate aDateValue; 294 ENSURE_OR_RETURN( i_value >>= aDateValue, "allowed for Date values only", returnValue ); 295 296 // convert 297 returnValue = lcl_convertDateToDays( aDateValue.Day, aDateValue.Month, aDateValue.Year ); 298 299 // done 300 return returnValue; 301 } 302 }; 303 304 //================================================================================================================== 305 //= TimeNormalization 306 //================================================================================================================== 307 class TimeNormalization : public StandardFormatNormalizer 308 { 309 public: 310 TimeNormalization( Reference< XNumberFormatter > const & i_formatter ) 311 :StandardFormatNormalizer( i_formatter, NumberFormat::TIME ) 312 { 313 } 314 315 virtual ~TimeNormalization() {} 316 317 virtual double convertToDouble( Any const & i_value ) const 318 { 319 double returnValue(0); 320 ::rtl::math::setNan( &returnValue ); 321 322 // extract 323 UnoTime aTimeValue; 324 ENSURE_OR_RETURN( i_value >>= aTimeValue, "allowed for Time values only", returnValue ); 325 326 // convert 327 returnValue += lcl_convertTimeToDays( 328 aTimeValue.Hours, aTimeValue.Minutes, aTimeValue.Seconds, aTimeValue.HundredthSeconds ); 329 330 // done 331 return returnValue; 332 } 333 }; 334 335 //================================================================================================================== 336 //= operations 337 //================================================================================================================== 338 namespace 339 { 340 //-------------------------------------------------------------------------------------------------------------- 341 bool lcl_ensureNumberFormatter( CellValueConversion_Data & io_data ) 342 { 343 if ( io_data.bAttemptedFormatterCreation ) 344 return io_data.xNumberFormatter.is(); 345 io_data.bAttemptedFormatterCreation = true; 346 347 try 348 { 349 // a number formatter 350 Reference< XNumberFormatter > const xFormatter( 351 io_data.aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW ); 352 353 // a supplier of number formats 354 Sequence< Any > aInitArgs(1); 355 aInitArgs[0] <<= SvtSysLocale().GetLocale(); 356 357 Reference< XNumberFormatsSupplier > const xSupplier( 358 io_data.aContext.createComponentWithArguments( "com.sun.star.util.NumberFormatsSupplier", aInitArgs ), 359 UNO_QUERY_THROW 360 ); 361 362 // ensure a NullDate we will assume later on 363 UnoDate const aNullDate( 1, 1, 1900 ); 364 Reference< XPropertySet > const xFormatSettings( xSupplier->getNumberFormatSettings(), UNO_SET_THROW ); 365 xFormatSettings->setPropertyValue( ::rtl::OUString::createFromAscii( "NullDate" ), makeAny( aNullDate ) ); 366 367 // knit 368 xFormatter->attachNumberFormatsSupplier( xSupplier ); 369 370 // done 371 io_data.xNumberFormatter = xFormatter; 372 } 373 catch( const Exception& ) 374 { 375 DBG_UNHANDLED_EXCEPTION(); 376 } 377 378 return io_data.xNumberFormatter.is(); 379 } 380 381 //-------------------------------------------------------------------------------------------------------------- 382 bool lcl_getValueNormalizer( CellValueConversion_Data & io_data, Type const & i_valueType, 383 PValueNormalization & o_formatter ) 384 { 385 NormalizerCache::const_iterator pos = io_data.aNormalizers.find( i_valueType.getTypeName() ); 386 if ( pos == io_data.aNormalizers.end() ) 387 { 388 // never encountered this type before 389 o_formatter.reset(); 390 391 ::rtl::OUString const sTypeName( i_valueType.getTypeName() ); 392 TypeClass const eTypeClass = i_valueType.getTypeClass(); 393 394 if ( sTypeName.equals( ::cppu::UnoType< DateTime >::get().getTypeName() ) ) 395 { 396 o_formatter.reset( new DateTimeNormalization( io_data.xNumberFormatter ) ); 397 } 398 else if ( sTypeName.equals( ::cppu::UnoType< UnoDate >::get().getTypeName() ) ) 399 { 400 o_formatter.reset( new DateNormalization( io_data.xNumberFormatter ) ); 401 } 402 else if ( sTypeName.equals( ::cppu::UnoType< UnoTime >::get().getTypeName() ) ) 403 { 404 o_formatter.reset( new TimeNormalization( io_data.xNumberFormatter ) ); 405 } 406 else if ( sTypeName.equals( ::cppu::UnoType< ::sal_Bool >::get().getTypeName() ) ) 407 { 408 o_formatter.reset( new BooleanNormalization( io_data.xNumberFormatter ) ); 409 } 410 else if ( sTypeName.equals( ::cppu::UnoType< double >::get().getTypeName() ) 411 || sTypeName.equals( ::cppu::UnoType< float >::get().getTypeName() ) 412 ) 413 { 414 o_formatter.reset( new DoubleNormalization( io_data.xNumberFormatter ) ); 415 } 416 else if ( ( eTypeClass == TypeClass_BYTE ) 417 || ( eTypeClass == TypeClass_SHORT ) 418 || ( eTypeClass == TypeClass_UNSIGNED_SHORT ) 419 || ( eTypeClass == TypeClass_LONG ) 420 || ( eTypeClass == TypeClass_UNSIGNED_LONG ) 421 || ( eTypeClass == TypeClass_HYPER ) 422 ) 423 { 424 o_formatter.reset( new IntegerNormalization( io_data.xNumberFormatter ) ); 425 } 426 else 427 { 428 #if OSL_DEBUG_LEVEL > 0 429 ::rtl::OStringBuffer message( "lcl_getValueNormalizer: unsupported type '" ); 430 message.append( ::rtl::OUStringToOString( sTypeName, RTL_TEXTENCODING_ASCII_US ) ); 431 message.append( "'!" ); 432 OSL_ENSURE( false, message.makeStringAndClear() ); 433 #endif 434 } 435 io_data.aNormalizers[ sTypeName ] = o_formatter; 436 } 437 else 438 o_formatter = pos->second; 439 440 return !!o_formatter; 441 } 442 } 443 444 //================================================================================================================== 445 //= CellValueConversion 446 //================================================================================================================== 447 //------------------------------------------------------------------------------------------------------------------ 448 CellValueConversion::CellValueConversion( ::comphelper::ComponentContext const & i_context ) 449 :m_pData( new CellValueConversion_Data( i_context ) ) 450 { 451 } 452 453 //------------------------------------------------------------------------------------------------------------------ 454 CellValueConversion::~CellValueConversion() 455 { 456 } 457 458 //------------------------------------------------------------------------------------------------------------------ 459 ::rtl::OUString CellValueConversion::convertToString( const Any& i_value ) 460 { 461 ::rtl::OUString sStringValue; 462 if ( !i_value.hasValue() ) 463 return sStringValue; 464 465 if ( ! ( i_value >>= sStringValue ) ) 466 { 467 if ( lcl_ensureNumberFormatter( *m_pData ) ) 468 { 469 PValueNormalization pNormalizer; 470 if ( lcl_getValueNormalizer( *m_pData, i_value.getValueType(), pNormalizer ) ) 471 { 472 try 473 { 474 double const formatterCompliantValue = pNormalizer->convertToDouble( i_value ); 475 sal_Int32 const formatKey = pNormalizer->getFormatKey(); 476 sStringValue = m_pData->xNumberFormatter->convertNumberToString( 477 formatKey, formatterCompliantValue ); 478 } 479 catch( const Exception& ) 480 { 481 DBG_UNHANDLED_EXCEPTION(); 482 } 483 } 484 } 485 } 486 487 return sStringValue; 488 } 489 490 //...................................................................................................................... 491 } // namespace svt 492 //...................................................................................................................... 493