Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / extensions / source / abpilot / fieldmappingimpl.cxx
blob64197737150ebdd0a4066a1b068415dfce2b981c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
37 namespace abp
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() )
65 return false;
67 try
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,
74 // the parent window
75 xDialogParent,
76 _rxDataSource,
77 _rSettings.bRegisterDataSource ? _rSettings.sRegisteredDataSourceName : _rSettings.sDataSourceName,
78 // the table to use
79 _rSettings.sSelectedTable,
80 sTitle);
82 // execute the dialog
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;
89 bool bSuccess =
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;
99 return true;
103 catch(const Exception&)
105 TOOLS_WARN_EXCEPTION("extensions.abpilot",
106 "caught an exception while executing the dialog!");
108 return false;
112 void defaultMapping( const Reference< XComponentContext >& _rxContext, MapString2String& _rFieldAssignment )
114 _rFieldAssignment.clear();
118 // what we have:
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",
132 "City", "HomeCity",
133 "State", "HomeState",
134 "Country", "HomeCountry",
135 "PhonePriv", "HomePhone",
136 "PhoneComp", "WorkPhone",
137 "PhoneCell", "CellularNumber",
138 "Pager", "PagerNumber",
139 "Fax", "FaxNumber",
140 "EMail", "PrimaryEmail",
141 "URL", "WebPage1",
142 "Note", "Notes",
143 "Altfield1", "Custom1",
144 "Altfield2", "Custom2",
145 "Altfield3", "Custom3",
146 "Altfield4", "Custom4",
147 "Title", "JobTitle",
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)
158 + "/ColumnAliases");
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!" );
167 // number of pairs
168 sal_Int32 const nIntersectedProgrammatics = std::size( pMappingProgrammatics ) / 2;
170 const char** pProgrammatic = pMappingProgrammatics;
171 OUString sAddressProgrammatic;
172 OUString sDriverProgrammatic;
173 OUString sDriverUI;
174 for ( sal_Int32 i=0;
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!");
189 else
190 _rFieldAssignment[ sAddressProgrammatic ] = sDriverUI;
192 else
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 )
227 SAL_WARN_IF(
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 )
238 { // yes
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 );
245 else
246 { // no
247 // -> remove it
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);
303 // set the flag
304 aAddressBookSettings.setNodeValue( OUString( "AutoPilotCompleted" ), Any( true ) );
306 // commit the changes done
307 aAddressBookSettings.commit();
311 } // namespace addressconfig
314 } // namespace abp
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */