merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / abpilot / fieldmappingimpl.cxx
blob93b2a55ea8bb49bc291f390197383483ce28297d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
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>
49 //.........................................................................
50 namespace abp
52 //.........................................................................
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;
63 //---------------------------------------------------------------------
64 static const ::rtl::OUString& lcl_getDriverSettingsNodeName()
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;
71 //---------------------------------------------------------------------
72 static const ::rtl::OUString& lcl_getAddressBookNodeName()
74 static const ::rtl::OUString s_sAddressBookNodeName =
75 ::rtl::OUString::createFromAscii( "/org.openoffice.Office.DataAccess/AddressBook" );
76 return s_sAddressBookNodeName;
79 //.....................................................................
80 namespace fieldmapping
82 //.....................................................................
84 //-----------------------------------------------------------------
85 sal_Bool invokeDialog( const Reference< XMultiServiceFactory >& _rxORB, class Window* _pParent,
86 const Reference< XPropertySet >& _rxDataSource, AddressSettings& _rSettings ) SAL_THROW ( ( ) )
88 _rSettings.aFieldMapping.clear();
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;
95 try
97 // ........................................................
98 // the parameters for creating the dialog
99 Sequence< Any > aArguments(5);
100 Any* pArguments = aArguments.getArray();
102 // the parent window
103 Reference< XWindow > xDialogParent = VCLUnoHelper::GetInterface( _pParent );
104 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "ParentWindow" ), -1, makeAny( xDialogParent ), PropertyState_DIRECT_VALUE);
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);
110 // the table to use
111 *pArguments++ <<= PropertyValue(::rtl::OUString::createFromAscii( "Command" ), -1, makeAny( _rSettings.sSelectedTable ), PropertyState_DIRECT_VALUE);
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);
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
124 if ( !xDialog.is( ) )
126 ShowServiceNotAvailableError( _pParent, s_sAdressBookFieldAssignmentServiceName, sal_True );
127 return sal_False;
130 // execute the dialog
131 if ( xDialog->execute() )
133 // retrieve the field mapping as set by he user
134 Reference< XPropertySet > xDialogProps( xDialog, UNO_QUERY );
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!" );
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;
149 return sal_True;
153 catch(const Exception&)
155 DBG_ERROR("fieldmapping::invokeDialog: caught an exception while executing the dialog!");
157 return sal_False;
160 //-----------------------------------------------------------------
161 void defaultMapping( const Reference< XMultiServiceFactory >& _rxORB, MapString2String& _rFieldAssignment ) SAL_THROW ( ( ) )
163 _rFieldAssignment.clear();
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[] =
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"
200 // (this list is not complete: both lists of programmatic names are larger in real,
201 // but this list above is the intersection)
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" );
208 // create a config node for this
209 OConfigurationTreeRoot aDriverFieldAliasing = OConfigurationTreeRoot::createWithServiceFactory(
210 _rxORB, sDriverAliasesNodeName, -1, OConfigurationTreeRoot::CM_READONLY);
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;
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;
227 sAddressProgrammatic = ::rtl::OUString::createFromAscii( *pProgrammatic++ );
228 sDriverProgrammatic = ::rtl::OUString::createFromAscii( *pProgrammatic++ );
230 if ( aDriverFieldAliasing.hasByName( sDriverProgrammatic ) )
232 aDriverFieldAliasing.getNodeValue( sDriverProgrammatic ) >>= sDriverUI;
233 if ( 0 == sDriverUI.getLength() )
235 DBG_ERROR( "fieldmapping::defaultMapping: invalid driver UI column name!");
237 else
238 _rFieldAssignment[ sAddressProgrammatic ] = sDriverUI;
240 else
242 DBG_ERROR( "fieldmapping::defaultMapping: invalid driver programmatic name!" );
246 catch( const Exception& )
248 DBG_ERROR("fieldmapping::defaultMapping: code is assumed to throw no exceptions!");
249 // the config nodes we're using herein should not do this ....
253 //-----------------------------------------------------------------
254 void writeTemplateAddressFieldMapping( const Reference< XMultiServiceFactory >& _rxORB, const MapString2String& _rFieldAssignment ) SAL_THROW ( ( ) )
256 // want to have a non-const map for easier handling
257 MapString2String aFieldAssignment( _rFieldAssignment );
259 // access the configuration information which the driver uses for determining it's column names
260 const ::rtl::OUString& sAddressBookNodeName = lcl_getAddressBookNodeName();
262 // create a config node for this
263 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithServiceFactory(
264 _rxORB, sAddressBookNodeName, -1, OConfigurationTreeRoot::CM_UPDATABLE);
266 OConfigurationNode aFields = aAddressBookSettings.openNode( ::rtl::OUString::createFromAscii( "Fields" ) );
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();
273 const ::rtl::OUString sProgrammaticNodeName = ::rtl::OUString::createFromAscii( "ProgrammaticFieldName" );
274 const ::rtl::OUString sAssignedNodeName = ::rtl::OUString::createFromAscii( "AssignedFieldName" );
276 for ( ; pExistentFields != pExistentFieldsEnd; ++pExistentFields )
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!
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 );
296 else
297 { // no
298 // -> remove it
299 aFields.removeNode( *pExistentFields );
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
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 ) );
319 // commit the changes done
320 aAddressBookSettings.commit();
323 //.....................................................................
324 } // namespace fieldmapping
325 //.....................................................................
327 //.....................................................................
328 namespace addressconfig
330 //.....................................................................
332 //-----------------------------------------------------------------
333 void writeTemplateAddressSource( const Reference< XMultiServiceFactory >& _rxORB,
334 const ::rtl::OUString& _rDataSourceName, const ::rtl::OUString& _rTableName ) SAL_THROW ( ( ) )
336 // access the configuration information which the driver uses for determining it's column names
337 const ::rtl::OUString& sAddressBookNodeName = lcl_getAddressBookNodeName();
339 // create a config node for this
340 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithServiceFactory(
341 _rxORB, sAddressBookNodeName, -1, OConfigurationTreeRoot::CM_UPDATABLE);
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 ) );
347 // commit the changes done
348 aAddressBookSettings.commit();
351 //-----------------------------------------------------------------
352 void markPilotSuccess( const Reference< XMultiServiceFactory >& _rxORB ) SAL_THROW ( ( ) )
354 // access the configuration information which the driver uses for determining it's column names
355 const ::rtl::OUString& sAddressBookNodeName = lcl_getAddressBookNodeName();
357 // create a config node for this
358 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithServiceFactory(
359 _rxORB, sAddressBookNodeName, -1, OConfigurationTreeRoot::CM_UPDATABLE);
361 // set the flag
362 aAddressBookSettings.setNodeValue( ::rtl::OUString::createFromAscii( "AutoPilotCompleted" ), makeAny( (sal_Bool)sal_True ) );
364 // commit the changes done
365 aAddressBookSettings.commit();
368 //.....................................................................
369 } // namespace addressconfig
370 //.....................................................................
372 //.........................................................................
373 } // namespace abp
374 //.........................................................................