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