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