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_extensions.hxx" 26 #include "fieldmappingimpl.hxx" 27 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 28 #include <com/sun/star/beans/PropertyValue.hpp> 29 #include <com/sun/star/beans/XPropertySet.hpp> 30 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> 31 #include <com/sun/star/awt/XWindow.hpp> 32 #include <com/sun/star/sdb/CommandType.hpp> 33 #include <tools/debug.hxx> 34 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ 35 #include <toolkit/helper/vclunohelper.hxx> 36 #endif 37 #include <vcl/stdtext.hxx> 38 #include <com/sun/star/util/AliasProgrammaticPair.hpp> 39 #ifndef EXTENSIONS_ABPRESID_HRC 40 #include "abpresid.hrc" 41 #endif 42 #include "componentmodule.hxx" 43 #include <unotools/confignode.hxx> 44 45 //......................................................................... 46 namespace abp 47 { 48 //......................................................................... 49 50 using namespace ::utl; 51 using namespace ::com::sun::star::uno; 52 using namespace ::com::sun::star::awt; 53 using namespace ::com::sun::star::util; 54 using namespace ::com::sun::star::lang; 55 using namespace ::com::sun::star::beans; 56 using namespace ::com::sun::star::sdb; 57 using namespace ::com::sun::star::ui::dialogs; 58 59 //--------------------------------------------------------------------- lcl_getDriverSettingsNodeName()60 static const ::rtl::OUString& lcl_getDriverSettingsNodeName() 61 { 62 static const ::rtl::OUString s_sDriverSettingsNodeName = 63 ::rtl::OUString::createFromAscii( "/org.openoffice.Office.DataAccess/DriverSettings/com.sun.star.comp.sdbc.MozabDriver" ); 64 return s_sDriverSettingsNodeName; 65 } 66 67 //--------------------------------------------------------------------- lcl_getAddressBookNodeName()68 static const ::rtl::OUString& lcl_getAddressBookNodeName() 69 { 70 static const ::rtl::OUString s_sAddressBookNodeName = 71 ::rtl::OUString::createFromAscii( "/org.openoffice.Office.DataAccess/AddressBook" ); 72 return s_sAddressBookNodeName; 73 } 74 75 //..................................................................... 76 namespace fieldmapping 77 { 78 //..................................................................... 79 80 //----------------------------------------------------------------- invokeDialog(const Reference<XMultiServiceFactory> & _rxORB,class Window * _pParent,const Reference<XPropertySet> & _rxDataSource,AddressSettings & _rSettings)81 sal_Bool invokeDialog( const Reference< XMultiServiceFactory >& _rxORB, class Window* _pParent, 82 const Reference< XPropertySet >& _rxDataSource, AddressSettings& _rSettings ) SAL_THROW ( ( ) ) 83 { 84 _rSettings.aFieldMapping.clear(); 85 86 DBG_ASSERT( _rxORB.is(), "fieldmapping::invokeDialog: invalid service factory!" ); 87 DBG_ASSERT( _rxDataSource.is(), "fieldmapping::invokeDialog: invalid data source!" ); 88 if ( !_rxORB.is() || !_rxDataSource.is() ) 89 return sal_False; 90 91 try 92 { 93 // ........................................................ 94 // the parameters for creating the dialog 95 Sequence< Any > aArguments(5); 96 Any* pArguments = aArguments.getArray(); 97 98 // the parent window 99 Reference< XWindow > xDialogParent = VCLUnoHelper::GetInterface( _pParent ); 100 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "ParentWindow" ), -1, makeAny( xDialogParent ), PropertyState_DIRECT_VALUE); 101 102 // the data source to use 103 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "DataSource" ), -1, makeAny( _rxDataSource ), PropertyState_DIRECT_VALUE); 104 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "DataSourceName" ), -1, makeAny( (sal_Bool)_rSettings.bRegisterDataSource ? _rSettings.sRegisteredDataSourceName : _rSettings.sDataSourceName ), PropertyState_DIRECT_VALUE); 105 106 // the table to use 107 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "Command" ), -1, makeAny( _rSettings.sSelectedTable ), PropertyState_DIRECT_VALUE); 108 109 // the title 110 ::rtl::OUString sTitle = String( ModuleRes( RID_STR_FIELDDIALOGTITLE ) ); 111 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "Title" ), -1, makeAny( sTitle ), PropertyState_DIRECT_VALUE); 112 113 // ........................................................ 114 // create an instance of the dialog service 115 static ::rtl::OUString s_sAdressBookFieldAssignmentServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.ui.AddressBookSourceDialog" ); 116 Reference< XExecutableDialog > xDialog( 117 _rxORB->createInstanceWithArguments( s_sAdressBookFieldAssignmentServiceName, aArguments ), 118 UNO_QUERY 119 ); 120 if ( !xDialog.is( ) ) 121 { 122 ShowServiceNotAvailableError( _pParent, s_sAdressBookFieldAssignmentServiceName, sal_True ); 123 return sal_False; 124 } 125 126 // execute the dialog 127 if ( xDialog->execute() ) 128 { 129 // retrieve the field mapping as set by he user 130 Reference< XPropertySet > xDialogProps( xDialog, UNO_QUERY ); 131 132 Sequence< AliasProgrammaticPair > aMapping; 133 #ifdef DBG_UTIL 134 sal_Bool bSuccess = 135 #endif 136 xDialogProps->getPropertyValue( ::rtl::OUString::createFromAscii( "FieldMapping" ) ) >>= aMapping; 137 DBG_ASSERT( bSuccess, "fieldmapping::invokeDialog: invalid property type for FieldMapping!" ); 138 139 // and copy it into the map 140 const AliasProgrammaticPair* pMapping = aMapping.getConstArray(); 141 const AliasProgrammaticPair* pMappingEnd = pMapping + aMapping.getLength(); 142 for (;pMapping != pMappingEnd; ++pMapping) 143 _rSettings.aFieldMapping[ pMapping->ProgrammaticName ] = pMapping->Alias; 144 145 return sal_True; 146 } 147 148 } 149 catch(const Exception&) 150 { 151 DBG_ERROR("fieldmapping::invokeDialog: caught an exception while executing the dialog!"); 152 } 153 return sal_False; 154 } 155 156 //----------------------------------------------------------------- defaultMapping(const Reference<XMultiServiceFactory> & _rxORB,MapString2String & _rFieldAssignment)157 void defaultMapping( const Reference< XMultiServiceFactory >& _rxORB, MapString2String& _rFieldAssignment ) SAL_THROW ( ( ) ) 158 { 159 _rFieldAssignment.clear(); 160 161 try 162 { 163 // what we have: 164 // a) For the address data source, we need a mapping from programmatic names (1) to real column names 165 // b) The SDBC driver has a fixed set of columns, which, when returned, are named according to 166 // some configuration entries. E.g., the driver displays the field which it knows contains 167 // the first name as "First Name" - the latter string is stored in the config. 168 // For this, the driver uses programmatic names, too, but they differ from the programmatic names the 169 // template documents have. 170 // So what we need first is a mapping from programmatic names (1) to programmatic names (2) 171 const sal_Char* pMappingProgrammatics[] = 172 { 173 "FirstName", "FirstName", 174 "LastName", "LastName", 175 "Street", "HomeAddress", 176 "Zip", "HomeZipCode", 177 "City", "HomeCity", 178 "State", "HomeState", 179 "Country", "HomeCountry", 180 "PhonePriv", "HomePhone", 181 "PhoneComp", "WorkPhone", 182 "PhoneCell", "CellularNumber", 183 "Pager", "PagerNumber", 184 "Fax", "FaxNumber", 185 "EMail", "PrimaryEmail", 186 "URL", "WebPage1", 187 "Note", "Notes", 188 "Altfield1", "Custom1", 189 "Altfield2", "Custom2", 190 "Altfield3", "Custom3", 191 "Altfield4", "Custom4", 192 "Title", "JobTitle", 193 "Company", "Company", 194 "Department", "Department" 195 }; 196 // (this list is not complete: both lists of programmatic names are larger in real, 197 // but this list above is the intersection) 198 199 200 // access the configuration information which the driver uses for determining it's column names 201 ::rtl::OUString sDriverAliasesNodeName = lcl_getDriverSettingsNodeName(); 202 sDriverAliasesNodeName += ::rtl::OUString::createFromAscii( "/ColumnAliases" ); 203 204 // create a config node for this 205 OConfigurationTreeRoot aDriverFieldAliasing = OConfigurationTreeRoot::createWithServiceFactory( 206 _rxORB, sDriverAliasesNodeName, -1, OConfigurationTreeRoot::CM_READONLY); 207 208 // loop through all programmatic pairs 209 DBG_ASSERT( 0 == ( sizeof( pMappingProgrammatics ) / sizeof( pMappingProgrammatics[ 0 ] ) ) % 2, 210 "fieldmapping::defaultMapping: invalid programmatic map!" ); 211 // number of pairs 212 sal_Int32 nIntersectedProgrammatics = sizeof( pMappingProgrammatics ) / sizeof( pMappingProgrammatics[ 0 ] ) / 2; 213 214 const sal_Char** pProgrammatic = pMappingProgrammatics; 215 ::rtl::OUString sAddressProgrammatic; 216 ::rtl::OUString sDriverProgrammatic; 217 ::rtl::OUString sDriverUI; 218 for ( sal_Int32 i=0; 219 i < nIntersectedProgrammatics; 220 ++i 221 ) 222 { 223 sAddressProgrammatic = ::rtl::OUString::createFromAscii( *pProgrammatic++ ); 224 sDriverProgrammatic = ::rtl::OUString::createFromAscii( *pProgrammatic++ ); 225 226 if ( aDriverFieldAliasing.hasByName( sDriverProgrammatic ) ) 227 { 228 aDriverFieldAliasing.getNodeValue( sDriverProgrammatic ) >>= sDriverUI; 229 if ( 0 == sDriverUI.getLength() ) 230 { 231 DBG_ERROR( "fieldmapping::defaultMapping: invalid driver UI column name!"); 232 } 233 else 234 _rFieldAssignment[ sAddressProgrammatic ] = sDriverUI; 235 } 236 else 237 { 238 DBG_ERROR( "fieldmapping::defaultMapping: invalid driver programmatic name!" ); 239 } 240 } 241 } 242 catch( const Exception& ) 243 { 244 DBG_ERROR("fieldmapping::defaultMapping: code is assumed to throw no exceptions!"); 245 // the config nodes we're using herein should not do this .... 246 } 247 } 248 249 //----------------------------------------------------------------- writeTemplateAddressFieldMapping(const Reference<XMultiServiceFactory> & _rxORB,const MapString2String & _rFieldAssignment)250 void writeTemplateAddressFieldMapping( const Reference< XMultiServiceFactory >& _rxORB, const MapString2String& _rFieldAssignment ) SAL_THROW ( ( ) ) 251 { 252 // want to have a non-const map for easier handling 253 MapString2String aFieldAssignment( _rFieldAssignment ); 254 255 // access the configuration information which the driver uses for determining it's column names 256 const ::rtl::OUString& sAddressBookNodeName = lcl_getAddressBookNodeName(); 257 258 // create a config node for this 259 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithServiceFactory( 260 _rxORB, sAddressBookNodeName, -1, OConfigurationTreeRoot::CM_UPDATABLE); 261 262 OConfigurationNode aFields = aAddressBookSettings.openNode( ::rtl::OUString::createFromAscii( "Fields" ) ); 263 264 // loop through all existent fields 265 Sequence< ::rtl::OUString > aExistentFields = aFields.getNodeNames(); 266 const ::rtl::OUString* pExistentFields = aExistentFields.getConstArray(); 267 const ::rtl::OUString* pExistentFieldsEnd = pExistentFields + aExistentFields.getLength(); 268 269 const ::rtl::OUString sProgrammaticNodeName = ::rtl::OUString::createFromAscii( "ProgrammaticFieldName" ); 270 const ::rtl::OUString sAssignedNodeName = ::rtl::OUString::createFromAscii( "AssignedFieldName" ); 271 272 for ( ; pExistentFields != pExistentFieldsEnd; ++pExistentFields ) 273 { 274 #ifdef DBG_UTIL 275 ::rtl::OUString sRedundantProgrammaticName; 276 aFields.openNode( *pExistentFields ).getNodeValue( sProgrammaticNodeName ) >>= sRedundantProgrammaticName; 277 #endif 278 DBG_ASSERT( sRedundantProgrammaticName == *pExistentFields, 279 "fieldmapping::writeTemplateAddressFieldMapping: inconsistent config data!" ); 280 // there should be a redundancy in the config data .... if this asserts, there isn't anymore! 281 282 // do we have a new alias for the programmatic? 283 MapString2StringIterator aPos = aFieldAssignment.find( *pExistentFields ); 284 if ( aFieldAssignment.end() != aPos ) 285 { // yes 286 // -> set a new value 287 OConfigurationNode aExistentField = aFields.openNode( *pExistentFields ); 288 aExistentField.setNodeValue( sAssignedNodeName, makeAny( aPos->second ) ); 289 // and remove the mapping entry 290 aFieldAssignment.erase( *pExistentFields ); 291 } 292 else 293 { // no 294 // -> remove it 295 aFields.removeNode( *pExistentFields ); 296 } 297 } 298 299 // now everything remaining in aFieldAssignment marks a mapping entry which was not present 300 // in the config before 301 for ( ConstMapString2StringIterator aNewMapping = aFieldAssignment.begin(); 302 aNewMapping != aFieldAssignment.end(); 303 ++aNewMapping 304 ) 305 { 306 DBG_ASSERT( !aFields.hasByName( aNewMapping->first ), 307 "fieldmapping::writeTemplateAddressFieldMapping: inconsistence!" ); 308 // in case the config node for the fields already has the node named <aNewMapping->first>, 309 // the entry should have been removed from aNewMapping (in the above loop) 310 OConfigurationNode aNewField = aFields.createNode( aNewMapping->first ); 311 aNewField.setNodeValue( sProgrammaticNodeName, makeAny( aNewMapping->first ) ); 312 aNewField.setNodeValue( sAssignedNodeName, makeAny( aNewMapping->second ) ); 313 } 314 315 // commit the changes done 316 aAddressBookSettings.commit(); 317 } 318 319 //..................................................................... 320 } // namespace fieldmapping 321 //..................................................................... 322 323 //..................................................................... 324 namespace addressconfig 325 { 326 //..................................................................... 327 328 //----------------------------------------------------------------- writeTemplateAddressSource(const Reference<XMultiServiceFactory> & _rxORB,const::rtl::OUString & _rDataSourceName,const::rtl::OUString & _rTableName)329 void writeTemplateAddressSource( const Reference< XMultiServiceFactory >& _rxORB, 330 const ::rtl::OUString& _rDataSourceName, const ::rtl::OUString& _rTableName ) SAL_THROW ( ( ) ) 331 { 332 // access the configuration information which the driver uses for determining it's column names 333 const ::rtl::OUString& sAddressBookNodeName = lcl_getAddressBookNodeName(); 334 335 // create a config node for this 336 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithServiceFactory( 337 _rxORB, sAddressBookNodeName, -1, OConfigurationTreeRoot::CM_UPDATABLE); 338 339 aAddressBookSettings.setNodeValue( ::rtl::OUString::createFromAscii( "DataSourceName" ), makeAny( _rDataSourceName ) ); 340 aAddressBookSettings.setNodeValue( ::rtl::OUString::createFromAscii( "Command" ), makeAny( _rTableName ) ); 341 aAddressBookSettings.setNodeValue( ::rtl::OUString::createFromAscii( "CommandType" ), makeAny( (sal_Int32)CommandType::TABLE ) ); 342 343 // commit the changes done 344 aAddressBookSettings.commit(); 345 } 346 347 //----------------------------------------------------------------- markPilotSuccess(const Reference<XMultiServiceFactory> & _rxORB)348 void markPilotSuccess( const Reference< XMultiServiceFactory >& _rxORB ) SAL_THROW ( ( ) ) 349 { 350 // access the configuration information which the driver uses for determining it's column names 351 const ::rtl::OUString& sAddressBookNodeName = lcl_getAddressBookNodeName(); 352 353 // create a config node for this 354 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithServiceFactory( 355 _rxORB, sAddressBookNodeName, -1, OConfigurationTreeRoot::CM_UPDATABLE); 356 357 // set the flag 358 aAddressBookSettings.setNodeValue( ::rtl::OUString::createFromAscii( "AutoPilotCompleted" ), makeAny( (sal_Bool)sal_True ) ); 359 360 // commit the changes done 361 aAddressBookSettings.commit(); 362 } 363 364 //..................................................................... 365 } // namespace addressconfig 366 //..................................................................... 367 368 //......................................................................... 369 } // namespace abp 370 //......................................................................... 371 372