LibreOffice Module extensions (master) 1
fieldmappingimpl.cxx
Go to the documentation of this file.
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/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>
28#include <vcl/weld.hxx>
29#include <com/sun/star/util/AliasProgrammaticPair.hpp>
30#include <strings.hrc>
31#include <componentmodule.hxx>
33#include <sal/log.hxx>
34
35
36namespace abp
37{
38
39
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;
49
50
51 const char16_t sDriverSettingsNodeName[] = u"/org.openoffice.Office.DataAccess/DriverSettings/com.sun.star.comp.sdbc.MozabDriver";
52 constexpr OUStringLiteral sAddressBookNodeName = u"/org.openoffice.Office.DataAccess/AddressBook";
53
54 namespace fieldmapping
55 {
56 bool invokeDialog( const Reference< XComponentContext >& _rxORB, class weld::Window* _pParent,
57 const Reference< XPropertySet >& _rxDataSource, AddressSettings& _rSettings )
58 {
59 _rSettings.aFieldMapping.clear();
60
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() )
64 return false;
65
66 try
67 {
68
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,
73 // the parent window
74 xDialogParent,
75 _rxDataSource,
76 _rSettings.bRegisterDataSource ? _rSettings.sRegisteredDataSourceName : _rSettings.sDataSourceName,
77 // the table to use
78 _rSettings.sSelectedTable,
79 sTitle);
80
81 // execute the dialog
82 if ( xDialog->execute() )
83 {
84 // retrieve the field mapping as set by he user
85 Reference< XPropertySet > xDialogProps( xDialog, UNO_QUERY );
86
87 Sequence< AliasProgrammaticPair > aMapping;
88 bool bSuccess =
89 xDialogProps->getPropertyValue("FieldMapping") >>= aMapping;
90 DBG_ASSERT( bSuccess, "fieldmapping::invokeDialog: invalid property type for FieldMapping!" );
91
92 // and copy it into the map
93 const AliasProgrammaticPair* pMapping = aMapping.getConstArray();
94 const AliasProgrammaticPair* pMappingEnd = pMapping + aMapping.getLength();
95 for (;pMapping != pMappingEnd; ++pMapping)
96 _rSettings.aFieldMapping[ pMapping->ProgrammaticName ] = pMapping->Alias;
97
98 return true;
99 }
100
101 }
102 catch(const Exception&)
103 {
104 TOOLS_WARN_EXCEPTION("extensions.abpilot",
105 "caught an exception while executing the dialog!");
106 }
107 return false;
108 }
109
110
111 void defaultMapping( const Reference< XComponentContext >& _rxContext, MapString2String& _rFieldAssignment )
112 {
113 _rFieldAssignment.clear();
114
115 try
116 {
117 // what we have:
118 // a) For the address data source, we need a mapping from programmatic names (1) to real column names
119 // b) The SDBC driver has a fixed set of columns, which, when returned, are named according to
120 // some configuration entries. E.g., the driver displays the field which it knows contains
121 // the first name as "First Name" - the latter string is stored in the config.
122 // For this, the driver uses programmatic names, too, but they differ from the programmatic names the
123 // template documents have.
124 // So what we need first is a mapping from programmatic names (1) to programmatic names (2)
125 const char* pMappingProgrammatics[] =
126 {
127 "FirstName", "FirstName",
128 "LastName", "LastName",
129 "Street", "HomeAddress",
130 "Zip", "HomeZipCode",
131 "City", "HomeCity",
132 "State", "HomeState",
133 "Country", "HomeCountry",
134 "PhonePriv", "HomePhone",
135 "PhoneComp", "WorkPhone",
136 "PhoneCell", "CellularNumber",
137 "Pager", "PagerNumber",
138 "Fax", "FaxNumber",
139 "EMail", "PrimaryEmail",
140 "URL", "WebPage1",
141 "Note", "Notes",
142 "Altfield1", "Custom1",
143 "Altfield2", "Custom2",
144 "Altfield3", "Custom3",
145 "Altfield4", "Custom4",
146 "Title", "JobTitle",
147 "Company", "Company",
148 "Department", "Department"
149 };
150 // (this list is not complete: both lists of programmatic names are larger in real,
151 // but this list above is the intersection)
152
153
154 // access the configuration information which the driver uses for determining its column names
155 OUString sDriverAliasesNodeName(
156 OUString::Concat(sDriverSettingsNodeName)
157 + "/ColumnAliases");
158
159 // create a config node for this
160 OConfigurationTreeRoot aDriverFieldAliasing = OConfigurationTreeRoot::createWithComponentContext(
161 _rxContext, sDriverAliasesNodeName, -1, OConfigurationTreeRoot::CM_READONLY);
162
163 // loop through all programmatic pairs
164 DBG_ASSERT( 0 == std::size( pMappingProgrammatics ) % 2,
165 "fieldmapping::defaultMapping: invalid programmatic map!" );
166 // number of pairs
167 sal_Int32 const nIntersectedProgrammatics = std::size( pMappingProgrammatics ) / 2;
168
169 const char** pProgrammatic = pMappingProgrammatics;
170 OUString sAddressProgrammatic;
171 OUString sDriverProgrammatic;
172 OUString sDriverUI;
173 for ( sal_Int32 i=0;
174 i < nIntersectedProgrammatics;
175 ++i
176 )
177 {
178 sAddressProgrammatic = OUString::createFromAscii( *pProgrammatic++ );
179 sDriverProgrammatic = OUString::createFromAscii( *pProgrammatic++ );
180
181 if ( aDriverFieldAliasing.hasByName( sDriverProgrammatic ) )
182 {
183 aDriverFieldAliasing.getNodeValue( sDriverProgrammatic ) >>= sDriverUI;
184 if ( 0 == sDriverUI.getLength() )
185 {
186 OSL_FAIL( "fieldmapping::defaultMapping: invalid driver UI column name!");
187 }
188 else
189 _rFieldAssignment[ sAddressProgrammatic ] = sDriverUI;
190 }
191 else
192 {
193 OSL_FAIL( "fieldmapping::defaultMapping: invalid driver programmatic name!" );
194 }
195 }
196 }
197 catch( const Exception& )
198 {
199 TOOLS_WARN_EXCEPTION("extensions.abpilot",
200 "code is assumed to throw no exceptions!");
201 // the config nodes we're using herein should not do this...
202 }
203 }
204
205
206 void writeTemplateAddressFieldMapping( const Reference< XComponentContext >& _rxContext, MapString2String&& aFieldAssignment )
207 {
208 // access the configuration information which the driver uses for determining its column names
209
210 // create a config node for this
211 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithComponentContext(
212 _rxContext, sAddressBookNodeName);
213
214 OConfigurationNode aFields = aAddressBookSettings.openNode( OUString( "Fields" ) );
215
216 // loop through all existent fields
217 Sequence< OUString > aExistentFields = aFields.getNodeNames();
218 const OUString* pExistentFields = aExistentFields.getConstArray();
219 const OUString* pExistentFieldsEnd = pExistentFields + aExistentFields.getLength();
220
221 static constexpr OUStringLiteral sProgrammaticNodeName( u"ProgrammaticFieldName" );
222 static constexpr OUStringLiteral sAssignedNodeName( u"AssignedFieldName" );
223
224 for ( ; pExistentFields != pExistentFieldsEnd; ++pExistentFields )
225 {
227 ((aFields.openNode(*pExistentFields)
228 .getNodeValue(sProgrammaticNodeName).get<OUString>())
229 != *pExistentFields),
230 "extensions.abpilot",
231 "fieldmapping::writeTemplateAddressFieldMapping: inconsistent config data!");
232 // there should be a redundancy in the config data... if this asserts, there isn't anymore!
233
234 // do we have a new alias for the programmatic?
235 MapString2String::iterator aPos = aFieldAssignment.find( *pExistentFields );
236 if ( aFieldAssignment.end() != aPos )
237 { // yes
238 // -> set a new value
239 OConfigurationNode aExistentField = aFields.openNode( *pExistentFields );
240 aExistentField.setNodeValue( sAssignedNodeName, Any( aPos->second ) );
241 // and remove the mapping entry
242 aFieldAssignment.erase( *pExistentFields );
243 }
244 else
245 { // no
246 // -> remove it
247 aFields.removeNode( *pExistentFields );
248 }
249 }
250
251 // now everything remaining in aFieldAssignment marks a mapping entry which was not present
252 // in the config before
253 for (auto const& elem : aFieldAssignment)
254 {
255 DBG_ASSERT( !aFields.hasByName( elem.first ),
256 "fieldmapping::writeTemplateAddressFieldMapping: inconsistence!" );
257 // in case the config node for the fields already has the node named <aNewMapping->first>,
258 // the entry should have been removed from aNewMapping (in the above loop)
259 OConfigurationNode aNewField = aFields.createNode( elem.first );
260 aNewField.setNodeValue( sProgrammaticNodeName, Any( elem.first ) );
261 aNewField.setNodeValue( sAssignedNodeName, Any( elem.second ) );
262 }
263
264 // commit the changes done
265 aAddressBookSettings.commit();
266 }
267
268
269 } // namespace fieldmapping
270
271
272 namespace addressconfig
273 {
274
275
276 void writeTemplateAddressSource( const Reference< XComponentContext >& _rxContext,
277 const OUString& _rDataSourceName, const OUString& _rTableName )
278 {
279 // access the configuration information which the driver uses for determining its column names
280
281 // create a config node for this
282 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithComponentContext(
283 _rxContext, sAddressBookNodeName);
284
285 aAddressBookSettings.setNodeValue( OUString( "DataSourceName" ), Any( _rDataSourceName ) );
286 aAddressBookSettings.setNodeValue( OUString( "Command" ), Any( _rTableName ) );
287 aAddressBookSettings.setNodeValue( OUString( "CommandType" ), Any( sal_Int16(CommandType::TABLE) ) );
288
289 // commit the changes done
290 aAddressBookSettings.commit();
291 }
292
293
294 void markPilotSuccess( const Reference< XComponentContext >& _rxContext )
295 {
296 // access the configuration information which the driver uses for determining its column names
297
298 // create a config node for this
299 OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithComponentContext(
300 _rxContext, sAddressBookNodeName);
301
302 // set the flag
303 aAddressBookSettings.setNodeValue( OUString( "AutoPilotCompleted" ), Any( true ) );
304
305 // commit the changes done
306 aAddressBookSettings.commit();
307 }
308
309
310 } // namespace addressconfig
311
312
313} // namespace abp
314
315
316/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Reference< css::awt::XWindow > GetXWindow()=0
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
uno_Mapping * pMapping
#define SAL_WARN_IF(condition, area, stream)
void markPilotSuccess(const Reference< XComponentContext > &_rxContext)
void writeTemplateAddressSource(const Reference< XComponentContext > &_rxContext, const OUString &_rDataSourceName, const OUString &_rTableName)
bool invokeDialog(const Reference< XComponentContext > &_rxORB, class weld::Window *_pParent, const Reference< XPropertySet > &_rxDataSource, AddressSettings &_rSettings)
void defaultMapping(const Reference< XComponentContext > &_rxContext, MapString2String &_rFieldAssignment)
void writeTemplateAddressFieldMapping(const Reference< XComponentContext > &_rxContext, MapString2String &&aFieldAssignment)
constexpr OUStringLiteral sAddressBookNodeName
const char16_t sDriverSettingsNodeName[]
std::map< OUString, OUString > MapString2String
Definition: abptypes.hxx:36
@ Exception
OUString ModuleRes(TranslateId pId)
int i
MapString2String aFieldMapping
OUString sRegisteredDataSourceName