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_connectivity.hxx" 26 27 #include "connectivity/formattedcolumnvalue.hxx" 28 #include "connectivity/dbtools.hxx" 29 #include "connectivity/dbconversion.hxx" 30 31 /** === begin UNO includes === **/ 32 #include <com/sun/star/util/XNumberFormatter.hpp> 33 #include <com/sun/star/util/Date.hpp> 34 #include <com/sun/star/sdbc/XConnection.hpp> 35 #include <com/sun/star/util/XNumberFormatTypes.hpp> 36 #include <com/sun/star/util/NumberFormat.hpp> 37 #include <com/sun/star/sdbc/DataType.hpp> 38 /** === end UNO includes === **/ 39 40 //#include <unotools/syslocale.hxx> 41 #include <tools/diagnose_ex.h> 42 #include <i18npool/mslangid.hxx> 43 #include <comphelper/numbers.hxx> 44 #include <comphelper/componentcontext.hxx> 45 #include <unotools/sharedunocomponent.hxx> 46 47 //........................................................................ 48 namespace dbtools 49 { 50 //........................................................................ 51 52 /** === begin UNO using === **/ 53 using ::com::sun::star::uno::Reference; 54 using ::com::sun::star::uno::UNO_QUERY; 55 using ::com::sun::star::uno::UNO_QUERY_THROW; 56 using ::com::sun::star::uno::UNO_SET_THROW; 57 using ::com::sun::star::uno::Exception; 58 using ::com::sun::star::uno::RuntimeException; 59 using ::com::sun::star::uno::Any; 60 using ::com::sun::star::uno::makeAny; 61 using ::com::sun::star::sdbc::XRowSet; 62 using ::com::sun::star::beans::XPropertySet; 63 using ::com::sun::star::util::XNumberFormatter; 64 using ::com::sun::star::util::Date; 65 using ::com::sun::star::sdbc::XConnection; 66 using ::com::sun::star::util::XNumberFormatsSupplier; 67 using ::com::sun::star::beans::XPropertySetInfo; 68 using ::com::sun::star::lang::Locale; 69 using ::com::sun::star::util::XNumberFormatTypes; 70 using ::com::sun::star::sdb::XColumn; 71 using ::com::sun::star::sdb::XColumnUpdate; 72 using ::com::sun::star::lang::XComponent; 73 /** === end UNO using === **/ 74 namespace DataType = ::com::sun::star::sdbc::DataType; 75 namespace NumberFormat = ::com::sun::star::util::NumberFormat; 76 77 //==================================================================== 78 //= FormattedColumnValue_Data 79 //==================================================================== 80 struct FormattedColumnValue_Data 81 { 82 Reference< XNumberFormatter > m_xFormatter; 83 Date m_aNullDate; 84 sal_Int32 m_nFormatKey; 85 sal_Int32 m_nFieldType; 86 sal_Int16 m_nKeyType; 87 bool m_bNumericField; 88 89 Reference< XColumn > m_xColumn; 90 Reference< XColumnUpdate > m_xColumnUpdate; 91 FormattedColumnValue_Datadbtools::FormattedColumnValue_Data92 FormattedColumnValue_Data() 93 :m_xFormatter() 94 ,m_aNullDate( DBTypeConversion::getStandardDate() ) 95 ,m_nFormatKey( 0 ) 96 ,m_nFieldType( DataType::OTHER ) 97 ,m_nKeyType( NumberFormat::UNDEFINED ) 98 ,m_bNumericField( false ) 99 ,m_xColumn() 100 ,m_xColumnUpdate() 101 { 102 } 103 }; 104 105 //-------------------------------------------------------------------- 106 namespace 107 { 108 //................................................................ lcl_clear_nothrow(FormattedColumnValue_Data & _rData)109 void lcl_clear_nothrow( FormattedColumnValue_Data& _rData ) 110 { 111 _rData.m_xFormatter.clear(); 112 _rData.m_nFormatKey = 0; 113 _rData.m_nFieldType = DataType::OTHER; 114 _rData.m_nKeyType = NumberFormat::UNDEFINED; 115 _rData.m_bNumericField = false; 116 117 _rData.m_xColumn.clear(); 118 _rData.m_xColumnUpdate.clear(); 119 } 120 121 //................................................................ lcl_initColumnDataValue_nothrow(FormattedColumnValue_Data & _rData,const Reference<XNumberFormatter> & i_rNumberFormatter,const Reference<XPropertySet> & _rxColumn)122 void lcl_initColumnDataValue_nothrow( FormattedColumnValue_Data& _rData, 123 const Reference< XNumberFormatter >& i_rNumberFormatter, const Reference< XPropertySet >& _rxColumn ) 124 { 125 lcl_clear_nothrow( _rData ); 126 127 OSL_PRECOND( i_rNumberFormatter.is(), "lcl_initColumnDataValue_nothrow: no number formats -> no formatted values!" ); 128 if ( !i_rNumberFormatter.is() ) 129 return; 130 131 try 132 { 133 Reference< XNumberFormatsSupplier > xNumberFormatsSupp( i_rNumberFormatter->getNumberFormatsSupplier(), UNO_SET_THROW ); 134 135 // remember the column 136 _rData.m_xColumn.set( _rxColumn, UNO_QUERY_THROW ); 137 _rData.m_xColumnUpdate.set( _rxColumn, UNO_QUERY ); 138 139 // determine the field type, and whether it's a numeric field 140 OSL_VERIFY( _rxColumn->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) ) >>= _rData.m_nFieldType ); 141 142 switch ( _rData.m_nFieldType ) 143 { 144 case DataType::DATE: 145 case DataType::TIME: 146 case DataType::TIMESTAMP: 147 case DataType::BIT: 148 case DataType::BOOLEAN: 149 case DataType::TINYINT: 150 case DataType::SMALLINT: 151 case DataType::INTEGER: 152 case DataType::REAL: 153 case DataType::BIGINT: 154 case DataType::DOUBLE: 155 case DataType::NUMERIC: 156 case DataType::DECIMAL: 157 _rData.m_bNumericField = true; 158 break; 159 default: 160 _rData.m_bNumericField = false; 161 break; 162 } 163 164 // get the format key of our bound field 165 Reference< XPropertySetInfo > xPSI( _rxColumn->getPropertySetInfo(), UNO_QUERY_THROW ); 166 bool bHaveFieldFormat = false; 167 const ::rtl::OUString sFormatKeyProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FormatKey" ) ) ); 168 if ( xPSI->hasPropertyByName( sFormatKeyProperty ) ) 169 { 170 bHaveFieldFormat = ( _rxColumn->getPropertyValue( sFormatKeyProperty ) >>= _rData.m_nFormatKey ); 171 } 172 if ( !bHaveFieldFormat ) 173 { 174 // fall back to a format key as indicated by the field type 175 Locale aSystemLocale; 176 MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage(), aSystemLocale ); 177 Reference< XNumberFormatTypes > xNumTypes( xNumberFormatsSupp->getNumberFormats(), UNO_QUERY_THROW ); 178 _rData.m_nFormatKey = getDefaultNumberFormat( _rxColumn, xNumTypes, aSystemLocale ); 179 } 180 181 // some more formatter settings 182 _rData.m_nKeyType = ::comphelper::getNumberFormatType( xNumberFormatsSupp->getNumberFormats(), _rData.m_nFormatKey ); 183 Reference< XPropertySet > xFormatSettings( xNumberFormatsSupp->getNumberFormatSettings(), UNO_QUERY_THROW ); 184 OSL_VERIFY( xFormatSettings->getPropertyValue( ::rtl::OUString::createFromAscii( "NullDate" ) ) >>= _rData.m_aNullDate ); 185 186 // remember the formatter 187 _rData.m_xFormatter = i_rNumberFormatter; 188 } 189 catch( const Exception& ) 190 { 191 DBG_UNHANDLED_EXCEPTION(); 192 } 193 } 194 195 //................................................................ lcl_initColumnDataValue_nothrow(const::comphelper::ComponentContext & i_rContext,FormattedColumnValue_Data & i_rData,const Reference<XRowSet> & i_rRowSet,const Reference<XPropertySet> & i_rColumn)196 void lcl_initColumnDataValue_nothrow( const ::comphelper::ComponentContext& i_rContext, FormattedColumnValue_Data& i_rData, 197 const Reference< XRowSet >& i_rRowSet, const Reference< XPropertySet >& i_rColumn ) 198 { 199 OSL_PRECOND( i_rRowSet.is(), "lcl_initColumnDataValue_nothrow: no row set!" ); 200 if ( !i_rRowSet.is() ) 201 return; 202 203 Reference< XNumberFormatter > xNumberFormatter; 204 try 205 { 206 // get the number formats supplier of the connection of the form 207 Reference< XConnection > xConnection( getConnection( i_rRowSet ), UNO_QUERY_THROW ); 208 Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( xConnection, sal_True, i_rContext.getLegacyServiceFactory() ), UNO_SET_THROW ); 209 210 // create a number formatter for it 211 xNumberFormatter.set( i_rContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW ); 212 xNumberFormatter->attachNumberFormatsSupplier( xSupplier ); 213 } 214 catch( const Exception& ) 215 { 216 DBG_UNHANDLED_EXCEPTION(); 217 } 218 219 lcl_initColumnDataValue_nothrow( i_rData, xNumberFormatter, i_rColumn ); 220 } 221 } 222 223 //==================================================================== 224 //= FormattedColumnValue 225 //==================================================================== 226 //-------------------------------------------------------------------- FormattedColumnValue(const::comphelper::ComponentContext & i_rContext,const Reference<XRowSet> & _rxRowSet,const Reference<XPropertySet> & i_rColumn)227 FormattedColumnValue::FormattedColumnValue( const ::comphelper::ComponentContext& i_rContext, 228 const Reference< XRowSet >& _rxRowSet, const Reference< XPropertySet >& i_rColumn ) 229 :m_pData( new FormattedColumnValue_Data ) 230 { 231 lcl_initColumnDataValue_nothrow( i_rContext, *m_pData, _rxRowSet, i_rColumn ); 232 } 233 234 //-------------------------------------------------------------------- FormattedColumnValue(const Reference<XNumberFormatter> & i_rNumberFormatter,const Reference<XPropertySet> & _rxColumn)235 FormattedColumnValue::FormattedColumnValue( const Reference< XNumberFormatter >& i_rNumberFormatter, 236 const Reference< XPropertySet >& _rxColumn ) 237 :m_pData( new FormattedColumnValue_Data ) 238 { 239 lcl_initColumnDataValue_nothrow( *m_pData, i_rNumberFormatter, _rxColumn ); 240 } 241 242 //-------------------------------------------------------------------- clear()243 void FormattedColumnValue::clear() 244 { 245 lcl_clear_nothrow( *m_pData ); 246 } 247 248 //-------------------------------------------------------------------- ~FormattedColumnValue()249 FormattedColumnValue::~FormattedColumnValue() 250 { 251 clear(); 252 } 253 254 //-------------------------------------------------------------------- getFormatKey() const255 sal_Int32 FormattedColumnValue::getFormatKey() const 256 { 257 return m_pData->m_nFormatKey; 258 } 259 260 //-------------------------------------------------------------------- getFieldType() const261 sal_Int32 FormattedColumnValue::getFieldType() const 262 { 263 return m_pData->m_nFieldType; 264 } 265 266 //-------------------------------------------------------------------- getKeyType() const267 sal_Int16 FormattedColumnValue::getKeyType() const 268 { 269 return m_pData->m_nKeyType; 270 } 271 272 //-------------------------------------------------------------------- isNumericField() const273 bool FormattedColumnValue::isNumericField() const 274 { 275 return m_pData->m_bNumericField; 276 } 277 278 //-------------------------------------------------------------------- getColumn() const279 const Reference< XColumn >& FormattedColumnValue::getColumn() const 280 { 281 return m_pData->m_xColumn; 282 } 283 284 //-------------------------------------------------------------------- getColumnUpdate() const285 const Reference< XColumnUpdate >& FormattedColumnValue::getColumnUpdate() const 286 { 287 return m_pData->m_xColumnUpdate; 288 } 289 290 //-------------------------------------------------------------------- setFormattedValue(const::rtl::OUString & _rFormattedStringValue) const291 bool FormattedColumnValue::setFormattedValue( const ::rtl::OUString& _rFormattedStringValue ) const 292 { 293 OSL_PRECOND( m_pData->m_xColumnUpdate.is(), "FormattedColumnValue::setFormattedValue: no column!" ); 294 if ( !m_pData->m_xColumnUpdate.is() ) 295 return false; 296 297 try 298 { 299 if ( m_pData->m_bNumericField ) 300 { 301 ::dbtools::DBTypeConversion::setValue( m_pData->m_xColumnUpdate, m_pData->m_xFormatter, m_pData->m_aNullDate, 302 _rFormattedStringValue, m_pData->m_nFormatKey, ::sal::static_int_cast< sal_Int16 >( m_pData->m_nFieldType ), 303 m_pData->m_nKeyType ); 304 } 305 else 306 { 307 m_pData->m_xColumnUpdate->updateString( _rFormattedStringValue ); 308 } 309 } 310 catch( const Exception& ) 311 { 312 return false; 313 } 314 return true; 315 } 316 317 //-------------------------------------------------------------------- getFormattedValue() const318 ::rtl::OUString FormattedColumnValue::getFormattedValue() const 319 { 320 OSL_PRECOND( m_pData->m_xColumn.is(), "FormattedColumnValue::setFormattedValue: no column!" ); 321 322 ::rtl::OUString sStringValue; 323 if ( m_pData->m_xColumn.is() ) 324 { 325 if ( m_pData->m_bNumericField ) 326 { 327 sStringValue = DBTypeConversion::getFormattedValue( 328 m_pData->m_xColumn, m_pData->m_xFormatter, m_pData->m_aNullDate, m_pData->m_nFormatKey, m_pData->m_nKeyType 329 ); 330 } 331 else 332 { 333 sStringValue = m_pData->m_xColumn->getString(); 334 } 335 } 336 return sStringValue; 337 } 338 339 //........................................................................ 340 } // namespace dbtools 341 //........................................................................ 342