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 #include "precompiled_reportdesign.hxx" 24 25 #include "formatnormalizer.hxx" 26 #include "RptModel.hxx" 27 28 /** === begin UNO includes === **/ 29 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 30 #include <com/sun/star/sdb/XParametersSupplier.hpp> 31 #include <com/sun/star/util/XNumberFormatTypes.hpp> 32 /** === end UNO includes === **/ 33 34 #include <dbaccess/dbsubcomponentcontroller.hxx> 35 #include <unotools/syslocale.hxx> 36 #include <connectivity/statementcomposer.hxx> 37 #include <connectivity/dbtools.hxx> 38 #include <tools/diagnose_ex.h> 39 40 //........................................................................ 41 namespace rptui 42 { 43 //........................................................................ 44 45 /** === begin UNO using === **/ 46 using ::com::sun::star::uno::Reference; 47 using ::com::sun::star::report::XReportDefinition; 48 using ::com::sun::star::report::XFormattedField; 49 using ::com::sun::star::uno::UNO_QUERY; 50 using ::com::sun::star::sdb::XSingleSelectQueryComposer; 51 using ::com::sun::star::sdbcx::XColumnsSupplier; 52 using ::com::sun::star::container::XIndexAccess; 53 using ::com::sun::star::beans::XPropertySet; 54 using ::com::sun::star::uno::UNO_QUERY_THROW; 55 using ::com::sun::star::uno::Exception; 56 using ::com::sun::star::sdb::XParametersSupplier; 57 using ::com::sun::star::sdbc::SQLException; 58 using ::com::sun::star::util::XNumberFormatsSupplier; 59 using ::com::sun::star::util::XNumberFormatTypes; 60 using ::com::sun::star::uno::makeAny; 61 /** === end UNO using === **/ 62 63 //==================================================================== 64 //= FormatNormalizer 65 //==================================================================== DBG_NAME(rpt_FormatNormalizer)66 DBG_NAME(rpt_FormatNormalizer) 67 //-------------------------------------------------------------------- 68 FormatNormalizer::FormatNormalizer( const OReportModel& _rModel ) 69 :m_rModel( _rModel ) 70 ,m_xReportDefinition( ) 71 ,m_bFieldListDirty( true ) 72 { 73 DBG_CTOR(rpt_FormatNormalizer,NULL); 74 } 75 76 //-------------------------------------------------------------------- ~FormatNormalizer()77 FormatNormalizer::~FormatNormalizer() 78 { 79 DBG_DTOR(rpt_FormatNormalizer,NULL); 80 } 81 82 //-------------------------------------------------------------------- notifyPropertyChange(const::com::sun::star::beans::PropertyChangeEvent & _rEvent)83 void FormatNormalizer::notifyPropertyChange( const ::com::sun::star::beans::PropertyChangeEvent& _rEvent ) 84 { 85 if ( !impl_lateInit() ) 86 return; 87 88 if ( ( _rEvent.Source == m_xReportDefinition ) && m_xReportDefinition.is() ) 89 { 90 impl_onDefinitionPropertyChange( _rEvent.PropertyName ); 91 return; 92 } 93 94 Reference< XFormattedField > xFormatted( _rEvent.Source, UNO_QUERY ); 95 if ( xFormatted.is() ) 96 impl_onFormattedProperttyChange( xFormatted, _rEvent.PropertyName ); 97 } 98 99 //-------------------------------------------------------------------- notifyElementInserted(const::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface> & _rxElement)100 void FormatNormalizer::notifyElementInserted( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement ) 101 { 102 if ( !impl_lateInit() ) 103 return; 104 105 Reference< XFormattedField > xFormatted( _rxElement, UNO_QUERY ); 106 if ( !xFormatted.is() ) 107 return; 108 109 impl_adjustFormatToDataFieldType_nothrow( xFormatted ); 110 } 111 112 //-------------------------------------------------------------------- impl_lateInit()113 bool FormatNormalizer::impl_lateInit() 114 { 115 if ( m_xReportDefinition.is() ) 116 return true; 117 118 m_xReportDefinition = m_rModel.getReportDefinition(); 119 return m_xReportDefinition.is(); 120 } 121 122 //-------------------------------------------------------------------- impl_onDefinitionPropertyChange(const::rtl::OUString & _rChangedPropName)123 void FormatNormalizer::impl_onDefinitionPropertyChange( const ::rtl::OUString& _rChangedPropName ) 124 { 125 if ( !_rChangedPropName.equalsAscii( "Command" ) 126 && !_rChangedPropName.equalsAscii( "CommandType" ) 127 && !_rChangedPropName.equalsAscii( "EscapeProcessing" ) 128 ) 129 // nothing we're interested in 130 return; 131 m_bFieldListDirty = true; 132 } 133 134 //-------------------------------------------------------------------- impl_onFormattedProperttyChange(const Reference<XFormattedField> & _rxFormatted,const::rtl::OUString & _rChangedPropName)135 void FormatNormalizer::impl_onFormattedProperttyChange( const Reference< XFormattedField >& _rxFormatted, const ::rtl::OUString& _rChangedPropName ) 136 { 137 if ( !_rChangedPropName.equalsAscii( "DataField" ) ) 138 // nothing we're interested in 139 return; 140 141 impl_adjustFormatToDataFieldType_nothrow( _rxFormatted ); 142 } 143 144 //-------------------------------------------------------------------- 145 namespace 146 { lcl_collectFields_throw(const Reference<XIndexAccess> & _rxColumns,FormatNormalizer::FieldList & _inout_rFields)147 void lcl_collectFields_throw( const Reference< XIndexAccess >& _rxColumns, FormatNormalizer::FieldList& _inout_rFields ) 148 { 149 try 150 { 151 sal_Int32 nCount( _rxColumns->getCount() ); 152 _inout_rFields.reserve( _inout_rFields.size() + (size_t)nCount ); 153 154 Reference< XPropertySet > xColumn; 155 FormatNormalizer::Field aField; 156 157 for ( sal_Int32 i=0; i<nCount; ++i ) 158 { 159 xColumn.set( _rxColumns->getByIndex( i ), UNO_QUERY_THROW ); 160 OSL_VERIFY( xColumn->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Name" ) ) ) >>= aField.sName ); 161 OSL_VERIFY( xColumn->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) ) >>= aField.nDataType ); 162 OSL_VERIFY( xColumn->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scale" ) ) ) >>= aField.nScale ); 163 OSL_VERIFY( xColumn->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsCurrency" ) ) ) >>= aField.bIsCurrency ); 164 _inout_rFields.push_back( aField ); 165 } 166 } 167 catch( const Exception& ) 168 { 169 DBG_UNHANDLED_EXCEPTION(); 170 } 171 } 172 } 173 174 //-------------------------------------------------------------------- impl_ensureUpToDateFieldList_nothrow()175 bool FormatNormalizer::impl_ensureUpToDateFieldList_nothrow() 176 { 177 if ( !m_bFieldListDirty ) 178 return true; 179 m_aFields.resize( 0 ); 180 181 OSL_PRECOND( m_xReportDefinition.is(), "FormatNormalizer::impl_ensureUpToDateFieldList_nothrow: no report definition!" ); 182 if ( !m_xReportDefinition.is() ) 183 return false; 184 185 ::dbaui::DBSubComponentController* pController( m_rModel.getController() ); 186 OSL_ENSURE( pController, "FormatNormalizer::impl_ensureUpToDateFieldList_nothrow: no controller? how can *this* happen?!" ); 187 if ( !pController ) 188 return false; 189 190 try 191 { 192 ::dbtools::StatementComposer aComposer( pController->getConnection(), m_xReportDefinition->getCommand(), 193 m_xReportDefinition->getCommandType(), m_xReportDefinition->getEscapeProcessing() ); 194 195 Reference< XSingleSelectQueryComposer > xComposer( aComposer.getComposer() ); 196 if ( !xComposer.is() ) 197 return false; 198 199 200 Reference< XColumnsSupplier > xSuppCols( xComposer, UNO_QUERY_THROW ); 201 Reference< XIndexAccess > xColumns( xSuppCols->getColumns(), UNO_QUERY_THROW ); 202 lcl_collectFields_throw( xColumns, m_aFields ); 203 204 Reference< XParametersSupplier > xSuppParams( xComposer, UNO_QUERY_THROW ); 205 Reference< XIndexAccess > xParams( xSuppParams->getParameters(), UNO_QUERY_THROW ); 206 lcl_collectFields_throw( xParams, m_aFields ); 207 } 208 catch( const SQLException& ) 209 { 210 // silence it. This might happen for instance when the user sets an non-existent table, 211 // or things like this 212 } 213 catch( const Exception& ) 214 { 215 DBG_UNHANDLED_EXCEPTION(); 216 } 217 218 m_bFieldListDirty = false; 219 return true; 220 } 221 222 //-------------------------------------------------------------------- impl_adjustFormatToDataFieldType_nothrow(const Reference<XFormattedField> & _rxFormatted)223 void FormatNormalizer::impl_adjustFormatToDataFieldType_nothrow( const Reference< XFormattedField >& _rxFormatted ) 224 { 225 if ( !impl_ensureUpToDateFieldList_nothrow() ) 226 // unable to obtain a recent field list 227 return; 228 229 try 230 { 231 sal_Int32 nFormatKey = _rxFormatted->getFormatKey(); 232 if ( nFormatKey != 0 ) 233 // it's not the "standard numeric" format -> not interested in 234 return; 235 236 ::rtl::OUString sDataField( _rxFormatted->getDataField() ); 237 const ::rtl::OUString sFieldPrefix( RTL_CONSTASCII_USTRINGPARAM( "field:[" ) ); 238 if ( sDataField.indexOf( sFieldPrefix ) != 0 ) 239 // not bound to a table field 240 // TODO: we might also do this kind of thing for functions and expressions ... 241 return; 242 if ( sDataField.getStr()[ sDataField.getLength() - 1 ] != ']' ) 243 { 244 // last character is not the closing brace 245 OSL_ENSURE( false, "FormatNormalizer::impl_adjustFormatToDataFieldType_nothrow: suspicious data field value!" ); 246 return; 247 } 248 sDataField = sDataField.copy( sFieldPrefix.getLength(), sDataField.getLength() - sFieldPrefix.getLength() - 1 ); 249 250 FieldList::const_iterator field = m_aFields.begin(); 251 for ( ; field != m_aFields.end(); ++field ) 252 { 253 if ( field->sName == sDataField ) 254 break; 255 } 256 if ( field == m_aFields.end() ) 257 // unknown field 258 return; 259 260 Reference< XNumberFormatsSupplier > xSuppNumFmts( _rxFormatted->getFormatsSupplier(), UNO_QUERY_THROW ); 261 Reference< XNumberFormatTypes > xNumFmtTypes( xSuppNumFmts->getNumberFormats(), UNO_QUERY_THROW ); 262 263 nFormatKey = ::dbtools::getDefaultNumberFormat( field->nDataType, field->nScale, field->bIsCurrency, xNumFmtTypes, 264 SvtSysLocale().GetLocaleData().getLocale() ); 265 _rxFormatted->setFormatKey( nFormatKey ); 266 } 267 catch( const Exception& ) 268 { 269 DBG_UNHANDLED_EXCEPTION(); 270 } 271 } 272 273 //........................................................................ 274 } // namespace rptui 275 //........................................................................ 276