xref: /AOO41X/main/extensions/source/abpilot/fieldmappingimpl.cxx (revision 2a97ec55f1442d65917e8c8b82a55ab76c9ff676)
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/unohlp.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