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