1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "fieldmappingimpl.hxx"
21 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
23 #include <com/sun/star/ui/AddressBookSourceDialog.hpp>
24 #include <com/sun/star/awt/XWindow.hpp>
25 #include <com/sun/star/sdb/CommandType.hpp>
26 #include <tools/debug.hxx>
27 #include <comphelper/diagnose_ex.hxx>
28 #include <vcl/weld.hxx>
29 #include <com/sun/star/util/AliasProgrammaticPair.hpp>
30 #include <strings.hrc>
31 #include <componentmodule.hxx>
32 #include <unotools/confignode.hxx>
33 #include <sal/macros.h>
34 #include <sal/log.hxx>
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
;
49 using namespace ::com::sun::star::ui::dialogs
;
52 const char16_t sDriverSettingsNodeName
[] = u
"/org.openoffice.Office.DataAccess/DriverSettings/com.sun.star.comp.sdbc.MozabDriver";
53 constexpr OUStringLiteral sAddressBookNodeName
= u
"/org.openoffice.Office.DataAccess/AddressBook";
55 namespace fieldmapping
57 bool invokeDialog( const Reference
< XComponentContext
>& _rxORB
, class weld::Window
* _pParent
,
58 const Reference
< XPropertySet
>& _rxDataSource
, AddressSettings
& _rSettings
)
60 _rSettings
.aFieldMapping
.clear();
62 DBG_ASSERT( _rxORB
.is(), "fieldmapping::invokeDialog: invalid service factory!" );
63 DBG_ASSERT( _rxDataSource
.is(), "fieldmapping::invokeDialog: invalid data source!" );
64 if ( !_rxORB
.is() || !_rxDataSource
.is() )
70 // create an instance of the dialog service
71 Reference
< XWindow
> xDialogParent
= _pParent
->GetXWindow();
72 OUString
sTitle(compmodule::ModuleRes(RID_STR_FIELDDIALOGTITLE
));
73 Reference
< XExecutableDialog
> xDialog
= AddressBookSourceDialog::createWithDataSource(_rxORB
,
77 _rSettings
.bRegisterDataSource
? _rSettings
.sRegisteredDataSourceName
: _rSettings
.sDataSourceName
,
79 _rSettings
.sSelectedTable
,
83 if ( xDialog
->execute() )
85 // retrieve the field mapping as set by he user
86 Reference
< XPropertySet
> xDialogProps( xDialog
, UNO_QUERY
);
88 Sequence
< AliasProgrammaticPair
> aMapping
;
90 xDialogProps
->getPropertyValue("FieldMapping") >>= aMapping
;
91 DBG_ASSERT( bSuccess
, "fieldmapping::invokeDialog: invalid property type for FieldMapping!" );
93 // and copy it into the map
94 const AliasProgrammaticPair
* pMapping
= aMapping
.getConstArray();
95 const AliasProgrammaticPair
* pMappingEnd
= pMapping
+ aMapping
.getLength();
96 for (;pMapping
!= pMappingEnd
; ++pMapping
)
97 _rSettings
.aFieldMapping
[ pMapping
->ProgrammaticName
] = pMapping
->Alias
;
103 catch(const Exception
&)
105 TOOLS_WARN_EXCEPTION("extensions.abpilot",
106 "caught an exception while executing the dialog!");
112 void defaultMapping( const Reference
< XComponentContext
>& _rxContext
, MapString2String
& _rFieldAssignment
)
114 _rFieldAssignment
.clear();
119 // a) For the address data source, we need a mapping from programmatic names (1) to real column names
120 // b) The SDBC driver has a fixed set of columns, which, when returned, are named according to
121 // some configuration entries. E.g., the driver displays the field which it knows contains
122 // the first name as "First Name" - the latter string is stored in the config.
123 // For this, the driver uses programmatic names, too, but they differ from the programmatic names the
124 // template documents have.
125 // So what we need first is a mapping from programmatic names (1) to programmatic names (2)
126 const char* pMappingProgrammatics
[] =
128 "FirstName", "FirstName",
129 "LastName", "LastName",
130 "Street", "HomeAddress",
131 "Zip", "HomeZipCode",
133 "State", "HomeState",
134 "Country", "HomeCountry",
135 "PhonePriv", "HomePhone",
136 "PhoneComp", "WorkPhone",
137 "PhoneCell", "CellularNumber",
138 "Pager", "PagerNumber",
140 "EMail", "PrimaryEmail",
143 "Altfield1", "Custom1",
144 "Altfield2", "Custom2",
145 "Altfield3", "Custom3",
146 "Altfield4", "Custom4",
148 "Company", "Company",
149 "Department", "Department"
151 // (this list is not complete: both lists of programmatic names are larger in real,
152 // but this list above is the intersection)
155 // access the configuration information which the driver uses for determining its column names
156 OUString
sDriverAliasesNodeName(
157 OUString::Concat(sDriverSettingsNodeName
)
160 // create a config node for this
161 OConfigurationTreeRoot aDriverFieldAliasing
= OConfigurationTreeRoot::createWithComponentContext(
162 _rxContext
, sDriverAliasesNodeName
, -1, OConfigurationTreeRoot::CM_READONLY
);
164 // loop through all programmatic pairs
165 DBG_ASSERT( 0 == std::size( pMappingProgrammatics
) % 2,
166 "fieldmapping::defaultMapping: invalid programmatic map!" );
168 sal_Int32
const nIntersectedProgrammatics
= std::size( pMappingProgrammatics
) / 2;
170 const char** pProgrammatic
= pMappingProgrammatics
;
171 OUString sAddressProgrammatic
;
172 OUString sDriverProgrammatic
;
175 i
< nIntersectedProgrammatics
;
179 sAddressProgrammatic
= OUString::createFromAscii( *pProgrammatic
++ );
180 sDriverProgrammatic
= OUString::createFromAscii( *pProgrammatic
++ );
182 if ( aDriverFieldAliasing
.hasByName( sDriverProgrammatic
) )
184 aDriverFieldAliasing
.getNodeValue( sDriverProgrammatic
) >>= sDriverUI
;
185 if ( 0 == sDriverUI
.getLength() )
187 OSL_FAIL( "fieldmapping::defaultMapping: invalid driver UI column name!");
190 _rFieldAssignment
[ sAddressProgrammatic
] = sDriverUI
;
194 OSL_FAIL( "fieldmapping::defaultMapping: invalid driver programmatic name!" );
198 catch( const Exception
& )
200 TOOLS_WARN_EXCEPTION("extensions.abpilot",
201 "code is assumed to throw no exceptions!");
202 // the config nodes we're using herein should not do this...
207 void writeTemplateAddressFieldMapping( const Reference
< XComponentContext
>& _rxContext
, MapString2String
&& aFieldAssignment
)
209 // access the configuration information which the driver uses for determining its column names
211 // create a config node for this
212 OConfigurationTreeRoot aAddressBookSettings
= OConfigurationTreeRoot::createWithComponentContext(
213 _rxContext
, sAddressBookNodeName
);
215 OConfigurationNode aFields
= aAddressBookSettings
.openNode( OUString( "Fields" ) );
217 // loop through all existent fields
218 Sequence
< OUString
> aExistentFields
= aFields
.getNodeNames();
219 const OUString
* pExistentFields
= aExistentFields
.getConstArray();
220 const OUString
* pExistentFieldsEnd
= pExistentFields
+ aExistentFields
.getLength();
222 static const OUStringLiteral
sProgrammaticNodeName( u
"ProgrammaticFieldName" );
223 static const OUStringLiteral
sAssignedNodeName( u
"AssignedFieldName" );
225 for ( ; pExistentFields
!= pExistentFieldsEnd
; ++pExistentFields
)
228 ((aFields
.openNode(*pExistentFields
)
229 .getNodeValue(sProgrammaticNodeName
).get
<OUString
>())
230 != *pExistentFields
),
231 "extensions.abpilot",
232 "fieldmapping::writeTemplateAddressFieldMapping: inconsistent config data!");
233 // there should be a redundancy in the config data... if this asserts, there isn't anymore!
235 // do we have a new alias for the programmatic?
236 MapString2String::iterator aPos
= aFieldAssignment
.find( *pExistentFields
);
237 if ( aFieldAssignment
.end() != aPos
)
239 // -> set a new value
240 OConfigurationNode aExistentField
= aFields
.openNode( *pExistentFields
);
241 aExistentField
.setNodeValue( sAssignedNodeName
, Any( aPos
->second
) );
242 // and remove the mapping entry
243 aFieldAssignment
.erase( *pExistentFields
);
248 aFields
.removeNode( *pExistentFields
);
252 // now everything remaining in aFieldAssignment marks a mapping entry which was not present
253 // in the config before
254 for (auto const& elem
: aFieldAssignment
)
256 DBG_ASSERT( !aFields
.hasByName( elem
.first
),
257 "fieldmapping::writeTemplateAddressFieldMapping: inconsistence!" );
258 // in case the config node for the fields already has the node named <aNewMapping->first>,
259 // the entry should have been removed from aNewMapping (in the above loop)
260 OConfigurationNode aNewField
= aFields
.createNode( elem
.first
);
261 aNewField
.setNodeValue( sProgrammaticNodeName
, Any( elem
.first
) );
262 aNewField
.setNodeValue( sAssignedNodeName
, Any( elem
.second
) );
265 // commit the changes done
266 aAddressBookSettings
.commit();
270 } // namespace fieldmapping
273 namespace addressconfig
277 void writeTemplateAddressSource( const Reference
< XComponentContext
>& _rxContext
,
278 const OUString
& _rDataSourceName
, const OUString
& _rTableName
)
280 // access the configuration information which the driver uses for determining its column names
282 // create a config node for this
283 OConfigurationTreeRoot aAddressBookSettings
= OConfigurationTreeRoot::createWithComponentContext(
284 _rxContext
, sAddressBookNodeName
);
286 aAddressBookSettings
.setNodeValue( OUString( "DataSourceName" ), Any( _rDataSourceName
) );
287 aAddressBookSettings
.setNodeValue( OUString( "Command" ), Any( _rTableName
) );
288 aAddressBookSettings
.setNodeValue( OUString( "CommandType" ), Any( sal_Int16(CommandType::TABLE
) ) );
290 // commit the changes done
291 aAddressBookSettings
.commit();
295 void markPilotSuccess( const Reference
< XComponentContext
>& _rxContext
)
297 // access the configuration information which the driver uses for determining its column names
299 // create a config node for this
300 OConfigurationTreeRoot aAddressBookSettings
= OConfigurationTreeRoot::createWithComponentContext(
301 _rxContext
, sAddressBookNodeName
);
304 aAddressBookSettings
.setNodeValue( OUString( "AutoPilotCompleted" ), Any( true ) );
306 // commit the changes done
307 aAddressBookSettings
.commit();
311 } // namespace addressconfig
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */