1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "connectivity/formattedcolumnvalue.hxx"
22 #include "connectivity/dbtools.hxx"
23 #include "connectivity/dbconversion.hxx"
25 #include <com/sun/star/util/NumberFormatter.hpp>
26 #include <com/sun/star/util/Date.hpp>
27 #include <com/sun/star/sdbc/XConnection.hpp>
28 #include <com/sun/star/util/XNumberFormatTypes.hpp>
29 #include <com/sun/star/util/NumberFormat.hpp>
30 #include <com/sun/star/sdbc/DataType.hpp>
32 #include <tools/diagnose_ex.h>
33 #include <i18nlangtag/mslangid.hxx>
34 #include <i18nlangtag/languagetag.hxx>
35 #include <comphelper/numbers.hxx>
36 #include <unotools/sharedunocomponent.hxx>
43 using ::com::sun::star::uno::Reference
;
44 using ::com::sun::star::uno::UNO_QUERY
;
45 using ::com::sun::star::uno::UNO_QUERY_THROW
;
46 using ::com::sun::star::uno::UNO_SET_THROW
;
47 using ::com::sun::star::uno::Exception
;
48 using ::com::sun::star::uno::RuntimeException
;
49 using ::com::sun::star::uno::Any
;
50 using ::com::sun::star::uno::makeAny
;
51 using ::com::sun::star::uno::XComponentContext
;
52 using ::com::sun::star::sdbc::XRowSet
;
53 using ::com::sun::star::beans::XPropertySet
;
54 using ::com::sun::star::util::NumberFormatter
;
55 using ::com::sun::star::util::XNumberFormatter
;
56 using ::com::sun::star::util::Date
;
57 using ::com::sun::star::sdbc::XConnection
;
58 using ::com::sun::star::util::XNumberFormatsSupplier
;
59 using ::com::sun::star::beans::XPropertySetInfo
;
60 using ::com::sun::star::lang::Locale
;
61 using ::com::sun::star::util::XNumberFormatTypes
;
62 using ::com::sun::star::sdb::XColumn
;
63 using ::com::sun::star::sdb::XColumnUpdate
;
64 using ::com::sun::star::lang::XComponent
;
66 namespace DataType
= ::com::sun::star::sdbc::DataType
;
67 namespace NumberFormat
= ::com::sun::star::util::NumberFormat
;
70 //= FormattedColumnValue_Data
72 struct FormattedColumnValue_Data
74 Reference
< XNumberFormatter
> m_xFormatter
;
76 sal_Int32 m_nFormatKey
;
77 sal_Int32 m_nFieldType
;
81 Reference
< XColumn
> m_xColumn
;
82 Reference
< XColumnUpdate
> m_xColumnUpdate
;
84 FormattedColumnValue_Data()
86 ,m_aNullDate( DBTypeConversion::getStandardDate() )
88 ,m_nFieldType( DataType::OTHER
)
89 ,m_nKeyType( NumberFormat::UNDEFINED
)
90 ,m_bNumericField( false )
101 void lcl_clear_nothrow( FormattedColumnValue_Data
& _rData
)
103 _rData
.m_xFormatter
.clear();
104 _rData
.m_nFormatKey
= 0;
105 _rData
.m_nFieldType
= DataType::OTHER
;
106 _rData
.m_nKeyType
= NumberFormat::UNDEFINED
;
107 _rData
.m_bNumericField
= false;
109 _rData
.m_xColumn
.clear();
110 _rData
.m_xColumnUpdate
.clear();
114 void lcl_initColumnDataValue_nothrow( FormattedColumnValue_Data
& _rData
,
115 const Reference
< XNumberFormatter
>& i_rNumberFormatter
, const Reference
< XPropertySet
>& _rxColumn
)
117 lcl_clear_nothrow( _rData
);
119 OSL_PRECOND( i_rNumberFormatter
.is(), "lcl_initColumnDataValue_nothrow: no number formats -> no formatted values!" );
120 if ( !i_rNumberFormatter
.is() )
125 Reference
< XNumberFormatsSupplier
> xNumberFormatsSupp( i_rNumberFormatter
->getNumberFormatsSupplier(), UNO_SET_THROW
);
127 // remember the column
128 _rData
.m_xColumn
.set( _rxColumn
, UNO_QUERY_THROW
);
129 _rData
.m_xColumnUpdate
.set( _rxColumn
, UNO_QUERY
);
131 // determine the field type, and whether it's a numeric field
132 OSL_VERIFY( _rxColumn
->getPropertyValue("Type") >>= _rData
.m_nFieldType
);
134 switch ( _rData
.m_nFieldType
)
138 case DataType::TIMESTAMP
:
140 case DataType::BOOLEAN
:
141 case DataType::TINYINT
:
142 case DataType::SMALLINT
:
143 case DataType::INTEGER
:
145 case DataType::BIGINT
:
146 case DataType::DOUBLE
:
147 case DataType::NUMERIC
:
148 case DataType::DECIMAL
:
149 _rData
.m_bNumericField
= true;
152 _rData
.m_bNumericField
= false;
156 // get the format key of our bound field
157 Reference
< XPropertySetInfo
> xPSI( _rxColumn
->getPropertySetInfo(), UNO_QUERY_THROW
);
158 bool bHaveFieldFormat
= false;
159 const OUString
sFormatKeyProperty( "FormatKey" );
160 if ( xPSI
->hasPropertyByName( sFormatKeyProperty
) )
162 bHaveFieldFormat
= ( _rxColumn
->getPropertyValue( sFormatKeyProperty
) >>= _rData
.m_nFormatKey
);
164 if ( !bHaveFieldFormat
)
166 // fall back to a format key as indicated by the field type
167 Locale
aSystemLocale( LanguageTag( MsLangId::getSystemLanguage() ).getLocale() );
168 Reference
< XNumberFormatTypes
> xNumTypes( xNumberFormatsSupp
->getNumberFormats(), UNO_QUERY_THROW
);
169 _rData
.m_nFormatKey
= getDefaultNumberFormat( _rxColumn
, xNumTypes
, aSystemLocale
);
172 // some more formatter settings
173 _rData
.m_nKeyType
= ::comphelper::getNumberFormatType( xNumberFormatsSupp
->getNumberFormats(), _rData
.m_nFormatKey
);
174 Reference
< XPropertySet
> xFormatSettings( xNumberFormatsSupp
->getNumberFormatSettings(), UNO_QUERY_THROW
);
175 OSL_VERIFY( xFormatSettings
->getPropertyValue("NullDate") >>= _rData
.m_aNullDate
);
177 // remember the formatter
178 _rData
.m_xFormatter
= i_rNumberFormatter
;
180 catch( const Exception
& )
182 DBG_UNHANDLED_EXCEPTION();
187 void lcl_initColumnDataValue_nothrow( const Reference
<XComponentContext
>& i_rContext
, FormattedColumnValue_Data
& i_rData
,
188 const Reference
< XRowSet
>& i_rRowSet
, const Reference
< XPropertySet
>& i_rColumn
)
190 OSL_PRECOND( i_rRowSet
.is(), "lcl_initColumnDataValue_nothrow: no row set!" );
191 if ( !i_rRowSet
.is() )
194 Reference
< XNumberFormatter
> xNumberFormatter
;
197 // get the number formats supplier of the connection of the form
198 Reference
< XConnection
> xConnection( getConnection( i_rRowSet
), UNO_QUERY_THROW
);
199 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats( xConnection
, true, i_rContext
), UNO_SET_THROW
);
201 // create a number formatter for it
202 xNumberFormatter
.set( NumberFormatter::create( i_rContext
), UNO_QUERY_THROW
);
203 xNumberFormatter
->attachNumberFormatsSupplier( xSupplier
);
205 catch( const Exception
& )
207 DBG_UNHANDLED_EXCEPTION();
210 lcl_initColumnDataValue_nothrow( i_rData
, xNumberFormatter
, i_rColumn
);
215 //= FormattedColumnValue
218 FormattedColumnValue::FormattedColumnValue( const Reference
< XComponentContext
>& _rxContext
,
219 const Reference
< XRowSet
>& _rxRowSet
, const Reference
< XPropertySet
>& i_rColumn
)
220 :m_pData( new FormattedColumnValue_Data
)
222 lcl_initColumnDataValue_nothrow( _rxContext
, *m_pData
, _rxRowSet
, i_rColumn
);
226 FormattedColumnValue::FormattedColumnValue( const Reference
< XNumberFormatter
>& i_rNumberFormatter
,
227 const Reference
< XPropertySet
>& _rxColumn
)
228 :m_pData( new FormattedColumnValue_Data
)
230 lcl_initColumnDataValue_nothrow( *m_pData
, i_rNumberFormatter
, _rxColumn
);
234 void FormattedColumnValue::clear()
236 lcl_clear_nothrow( *m_pData
);
240 FormattedColumnValue::~FormattedColumnValue()
246 sal_Int32
FormattedColumnValue::getFormatKey() const
248 return m_pData
->m_nFormatKey
;
252 sal_Int32
FormattedColumnValue::getFieldType() const
254 return m_pData
->m_nFieldType
;
258 sal_Int16
FormattedColumnValue::getKeyType() const
260 return m_pData
->m_nKeyType
;
264 const Reference
< XColumn
>& FormattedColumnValue::getColumn() const
266 return m_pData
->m_xColumn
;
270 const Reference
< XColumnUpdate
>& FormattedColumnValue::getColumnUpdate() const
272 return m_pData
->m_xColumnUpdate
;
276 bool FormattedColumnValue::setFormattedValue( const OUString
& _rFormattedStringValue
) const
278 OSL_PRECOND( m_pData
->m_xColumnUpdate
.is(), "FormattedColumnValue::setFormattedValue: no column!" );
279 if ( !m_pData
->m_xColumnUpdate
.is() )
284 if ( m_pData
->m_bNumericField
)
286 ::dbtools::DBTypeConversion::setValue( m_pData
->m_xColumnUpdate
, m_pData
->m_xFormatter
, m_pData
->m_aNullDate
,
287 _rFormattedStringValue
, m_pData
->m_nFormatKey
, ::sal::static_int_cast
< sal_Int16
>( m_pData
->m_nFieldType
),
288 m_pData
->m_nKeyType
);
292 m_pData
->m_xColumnUpdate
->updateString( _rFormattedStringValue
);
295 catch( const Exception
& )
303 OUString
FormattedColumnValue::getFormattedValue() const
305 OSL_PRECOND( m_pData
->m_xColumn
.is(), "FormattedColumnValue::setFormattedValue: no column!" );
307 OUString sStringValue
;
308 if ( m_pData
->m_xColumn
.is() )
310 if ( m_pData
->m_bNumericField
)
312 sStringValue
= DBTypeConversion::getFormattedValue(
313 m_pData
->m_xColumn
, m_pData
->m_xFormatter
, m_pData
->m_aNullDate
, m_pData
->m_nFormatKey
, m_pData
->m_nKeyType
318 sStringValue
= m_pData
->m_xColumn
->getString();
325 } // namespace dbtools
328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */