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/log.hxx>
40 using namespace ::utl
;
41 using namespace ::com::sun::star::uno
;
42 using namespace ::com::sun::star::awt
;
43 using namespace ::com::sun::star::util
;
44 using namespace ::com::sun::star::lang
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::com::sun::star::sdb
;
47 using namespace ::com::sun::star::ui
;
48 using namespace ::com::sun::star::ui::dialogs
;
51 const char16_t sDriverSettingsNodeName
[] = u
"/org.openoffice.Office.DataAccess/DriverSettings/com.sun.star.comp.sdbc.MozabDriver";
52 constexpr OUString sAddressBookNodeName
= u
"/org.openoffice.Office.DataAccess/AddressBook"_ustr
;
54 namespace fieldmapping
56 bool invokeDialog( const Reference
< XComponentContext
>& _rxORB
, class weld::Window
* _pParent
,
57 const Reference
< XPropertySet
>& _rxDataSource
, AddressSettings
& _rSettings
)
59 _rSettings
.aFieldMapping
.clear();
61 DBG_ASSERT( _rxORB
.is(), "fieldmapping::invokeDialog: invalid service factory!" );
62 DBG_ASSERT( _rxDataSource
.is(), "fieldmapping::invokeDialog: invalid data source!" );
63 if ( !_rxORB
.is() || !_rxDataSource
.is() )
69 // create an instance of the dialog service
70 Reference
< XWindow
> xDialogParent
= _pParent
->GetXWindow();
71 OUString
sTitle(compmodule::ModuleRes(RID_STR_FIELDDIALOGTITLE
));
72 Reference
< XExecutableDialog
> xDialog
= AddressBookSourceDialog::createWithDataSource(_rxORB
,
76 _rSettings
.bRegisterDataSource
? _rSettings
.sRegisteredDataSourceName
: _rSettings
.sDataSourceName
,
78 _rSettings
.sSelectedTable
,
82 if ( xDialog
->execute() )
84 // retrieve the field mapping as set by he user
85 Reference
< XPropertySet
> xDialogProps( xDialog
, UNO_QUERY
);
87 Sequence
< AliasProgrammaticPair
> aMapping
;
89 xDialogProps
->getPropertyValue(u
"FieldMapping"_ustr
) >>= aMapping
;
90 DBG_ASSERT( bSuccess
, "fieldmapping::invokeDialog: invalid property type for FieldMapping!" );
92 // and copy it into the map
93 for (auto& rMapping
: aMapping
)
94 _rSettings
.aFieldMapping
[rMapping
.ProgrammaticName
] = rMapping
.Alias
;
100 catch(const Exception
&)
102 TOOLS_WARN_EXCEPTION("extensions.abpilot",
103 "caught an exception while executing the dialog!");
109 void defaultMapping( const Reference
< XComponentContext
>& _rxContext
, MapString2String
& _rFieldAssignment
)
111 _rFieldAssignment
.clear();
116 // a) For the address data source, we need a mapping from programmatic names (1) to real column names
117 // b) The SDBC driver has a fixed set of columns, which, when returned, are named according to
118 // some configuration entries. E.g., the driver displays the field which it knows contains
119 // the first name as "First Name" - the latter string is stored in the config.
120 // For this, the driver uses programmatic names, too, but they differ from the programmatic names the
121 // template documents have.
122 // So what we need first is a mapping from programmatic names (1) to programmatic names (2)
123 const char* pMappingProgrammatics
[] =
125 "FirstName", "FirstName",
126 "LastName", "LastName",
127 "Street", "HomeAddress",
128 "Zip", "HomeZipCode",
130 "State", "HomeState",
131 "Country", "HomeCountry",
132 "PhonePriv", "HomePhone",
133 "PhoneComp", "WorkPhone",
134 "PhoneCell", "CellularNumber",
135 "Pager", "PagerNumber",
137 "EMail", "PrimaryEmail",
140 "Altfield1", "Custom1",
141 "Altfield2", "Custom2",
142 "Altfield3", "Custom3",
143 "Altfield4", "Custom4",
145 "Company", "Company",
146 "Department", "Department"
148 // (this list is not complete: both lists of programmatic names are larger in real,
149 // but this list above is the intersection)
152 // access the configuration information which the driver uses for determining its column names
153 OUString
sDriverAliasesNodeName(
154 OUString::Concat(sDriverSettingsNodeName
)
157 // create a config node for this
158 OConfigurationTreeRoot aDriverFieldAliasing
= OConfigurationTreeRoot::createWithComponentContext(
159 _rxContext
, sDriverAliasesNodeName
, -1, OConfigurationTreeRoot::CM_READONLY
);
161 // loop through all programmatic pairs
162 DBG_ASSERT( 0 == std::size( pMappingProgrammatics
) % 2,
163 "fieldmapping::defaultMapping: invalid programmatic map!" );
165 sal_Int32
const nIntersectedProgrammatics
= std::size( pMappingProgrammatics
) / 2;
167 const char** pProgrammatic
= pMappingProgrammatics
;
168 OUString sAddressProgrammatic
;
169 OUString sDriverProgrammatic
;
172 i
< nIntersectedProgrammatics
;
176 sAddressProgrammatic
= OUString::createFromAscii( *pProgrammatic
++ );
177 sDriverProgrammatic
= OUString::createFromAscii( *pProgrammatic
++ );
179 if ( aDriverFieldAliasing
.hasByName( sDriverProgrammatic
) )
181 aDriverFieldAliasing
.getNodeValue( sDriverProgrammatic
) >>= sDriverUI
;
182 if ( 0 == sDriverUI
.getLength() )
184 OSL_FAIL( "fieldmapping::defaultMapping: invalid driver UI column name!");
187 _rFieldAssignment
[ sAddressProgrammatic
] = sDriverUI
;
191 OSL_FAIL( "fieldmapping::defaultMapping: invalid driver programmatic name!" );
195 catch( const Exception
& )
197 TOOLS_WARN_EXCEPTION("extensions.abpilot",
198 "code is assumed to throw no exceptions!");
199 // the config nodes we're using herein should not do this...
204 void writeTemplateAddressFieldMapping( const Reference
< XComponentContext
>& _rxContext
, MapString2String
&& aFieldAssignment
)
206 // access the configuration information which the driver uses for determining its column names
208 // create a config node for this
209 OConfigurationTreeRoot aAddressBookSettings
= OConfigurationTreeRoot::createWithComponentContext(
210 _rxContext
, sAddressBookNodeName
);
212 OConfigurationNode aFields
= aAddressBookSettings
.openNode( u
"Fields"_ustr
);
214 // loop through all existent fields
215 static constexpr OUString
sProgrammaticNodeName( u
"ProgrammaticFieldName"_ustr
);
216 static constexpr OUString
sAssignedNodeName( u
"AssignedFieldName"_ustr
);
218 for (auto& rExistentField
: aFields
.getNodeNames())
221 ((aFields
.openNode(rExistentField
)
222 .getNodeValue(sProgrammaticNodeName
).get
<OUString
>())
224 "extensions.abpilot",
225 "fieldmapping::writeTemplateAddressFieldMapping: inconsistent config data!");
226 // there should be a redundancy in the config data... if this asserts, there isn't anymore!
228 // do we have a new alias for the programmatic?
229 MapString2String::iterator aPos
= aFieldAssignment
.find(rExistentField
);
230 if ( aFieldAssignment
.end() != aPos
)
232 // -> set a new value
233 OConfigurationNode aExistentField
= aFields
.openNode(rExistentField
);
234 aExistentField
.setNodeValue( sAssignedNodeName
, Any( aPos
->second
) );
235 // and remove the mapping entry
236 aFieldAssignment
.erase(rExistentField
);
241 aFields
.removeNode(rExistentField
);
245 // now everything remaining in aFieldAssignment marks a mapping entry which was not present
246 // in the config before
247 for (auto const& elem
: aFieldAssignment
)
249 DBG_ASSERT( !aFields
.hasByName( elem
.first
),
250 "fieldmapping::writeTemplateAddressFieldMapping: inconsistence!" );
251 // in case the config node for the fields already has the node named <aNewMapping->first>,
252 // the entry should have been removed from aNewMapping (in the above loop)
253 OConfigurationNode aNewField
= aFields
.createNode( elem
.first
);
254 aNewField
.setNodeValue( sProgrammaticNodeName
, Any( elem
.first
) );
255 aNewField
.setNodeValue( sAssignedNodeName
, Any( elem
.second
) );
258 // commit the changes done
259 aAddressBookSettings
.commit();
263 } // namespace fieldmapping
266 namespace addressconfig
270 void writeTemplateAddressSource( const Reference
< XComponentContext
>& _rxContext
,
271 const OUString
& _rDataSourceName
, const OUString
& _rTableName
)
273 // access the configuration information which the driver uses for determining its column names
275 // create a config node for this
276 OConfigurationTreeRoot aAddressBookSettings
= OConfigurationTreeRoot::createWithComponentContext(
277 _rxContext
, sAddressBookNodeName
);
279 aAddressBookSettings
.setNodeValue( u
"DataSourceName"_ustr
, Any( _rDataSourceName
) );
280 aAddressBookSettings
.setNodeValue( u
"Command"_ustr
, Any( _rTableName
) );
281 aAddressBookSettings
.setNodeValue( u
"CommandType"_ustr
, Any( sal_Int16(CommandType::TABLE
) ) );
283 // commit the changes done
284 aAddressBookSettings
.commit();
288 void markPilotSuccess( const Reference
< XComponentContext
>& _rxContext
)
290 // access the configuration information which the driver uses for determining its column names
292 // create a config node for this
293 OConfigurationTreeRoot aAddressBookSettings
= OConfigurationTreeRoot::createWithComponentContext(
294 _rxContext
, sAddressBookNodeName
);
297 aAddressBookSettings
.setNodeValue( u
"AutoPilotCompleted"_ustr
, Any( true ) );
299 // commit the changes done
300 aAddressBookSettings
.commit();
304 } // namespace addressconfig
310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */