lib+tools: updated strings to support i18n translations
[barry.git] / desktop / src / osconfig.cc
blob3e077b37bd2bb2bf0d576ceb51faf52c8521d8af
1 ///
2 /// \file osconfig.cc
3 /// Class which detects a set of available or known devices
4 /// in an opensync-able system.
5 ///
7 /*
8 Copyright (C) 2009-2012, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "osconfig.h"
24 #include "os40.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <algorithm>
30 #include "i18n.h"
32 using namespace std;
33 using namespace Barry;
35 namespace OpenSync { namespace Config {
37 //////////////////////////////////////////////////////////////////////////////
38 // Unsupported config class
40 std::string Unsupported::AppName()
42 return _C("Unsupported");
46 //////////////////////////////////////////////////////////////////////////////
47 // Barry config class
49 Barry::Barry(const ::Barry::Pin &pin)
50 : m_debug_mode(false)
51 , m_pin(pin)
53 if( !m_pin.Valid() )
54 throw std::logic_error(_C("Barry config must have valid pin number."));
57 Barry::Barry(Converter *load_converter, const Member &member)
58 : m_debug_mode(false)
60 load_converter->Load(*this, member);
62 // check that the loaded pin is valid... if not, it is
63 // likely safe to assume that something is horribly wrong.
64 // in the case where the Application wishes to add a new
65 // barry plugin, it should use the Pin constructor.
66 // if you *really* need to try to salvage an old
67 // corrupt config, you can always do the
68 // converter->Load(barry_obj) manually, and pick out
69 // the left overs.
71 if( !m_pin.Valid() ) {
72 std::ostringstream oss;
73 oss << _C("Unable to load pin number from Barry plugin config. Consider this group corrupt, or not fully configured: ") << member;
74 throw LoadError(oss.str());
79 //////////////////////////////////////////////////////////////////////////////
80 // Group class
82 Group::Group(const std::string &group_name,
83 OpenSync::API &api,
84 unsigned throw_mask)
85 : m_group_name(group_name)
87 Load(api, throw_mask);
90 Group::Group(const std::string &group_name)
91 : m_group_name(group_name)
95 // Checks for OSCG_THROW_ON_NO_BARRY and OSCG_THROW_ON_MULTIPLE_BARRIES
96 void Group::BarryCheck(OpenSync::API &api,
97 const std::string &group_name,
98 const member_list_type &members,
99 unsigned throw_mask)
101 if( ! (throw_mask & (OSCG_THROW_ON_NO_BARRY | OSCG_THROW_ON_MULTIPLE_BARRIES) ) )
102 return; // nothing to do
104 int found = 0;
105 std::string barry_name = Config::Barry::PluginName(api);
106 member_list_type::const_iterator b = members.begin(), e = members.end();
107 for( ; b != e; ++b ) {
108 if( b->plugin_name == barry_name )
109 found++;
112 if( found == 0 && (throw_mask & OSCG_THROW_ON_NO_BARRY) ) {
113 throw LoadError(
114 string_vprintf(_C("No Barry plugins found in group '%s' and OSCG_THROW_ON_NO_BARRY is set."), group_name.c_str()));
117 if( found > 1 && (throw_mask & OSCG_THROW_ON_MULTIPLE_BARRIES) ) {
118 throw LoadError(
119 string_vprintf(_C("Found %d Barry plugins in group '%s' and OSCG_THROW_ON_MULTIPLE_BARRIES is set."), found, group_name.c_str()));
123 bool Group::GroupMatchesExistingConfig(OpenSync::API &api)
125 member_list_type members;
126 api.GetMembers(m_group_name, members);
128 // what needs to match:
130 // - number of connected Config::Plugin objects in our
131 // list must match number of members in config
132 // - each member ID must match along with the plugin_name
133 // of each member
136 // check totals match
137 if( (unsigned) GetConnectedCount() != members.size() ) {
138 barryverbose("Connected count of " << GetConnectedCount() << " does not match member count of " << members.size());
139 return false;
142 // cycle through our own vector, matching against each member_id
143 // in the members list
144 const_iterator ci = begin(), ce = end();
145 for( ; ci != ce; ++ci ) {
146 if( (*ci)->GetMemberId() == -1 )
147 continue;
149 Member *m = members.Find( (*ci)->GetMemberId() );
150 if( !m ) {
151 barryverbose("Can't match member ID: " << (*ci)->GetMemberId() );
152 return false;
155 if( m->plugin_name != (*ci)->GetPluginName(api) ) {
156 barryverbose("Plugin names don't match: "
157 << m->plugin_name << ", "
158 << (*ci)->GetPluginName(api));
159 return false;
163 return true;
166 bool Group::HasUnsupportedPlugins() const
168 const_iterator b = begin(), e = end();
169 for( ; b != e; ++b ) {
170 if( (*b)->IsUnsupported() )
171 return true;
173 return false;
176 bool Group::HasBarryPlugins() const
178 const_iterator b = begin(), e = end();
179 for( ; b != e; ++b ) {
180 if( (*b)->GetAppName() == Config::Barry::AppName() )
181 return true;
183 return false;
186 bool Group::GroupExists(OpenSync::API &api) const
188 // does m_group_name exist in the API list?
189 string_list_type groups;
190 api.GetGroupNames(groups);
191 return std::find(groups.begin(), groups.end(), m_group_name) != groups.end();
194 bool Group::AllConfigured(OpenSync::API &api) const
196 const_iterator b = begin(), e = end();
197 for( ; b != e; ++b ) {
198 if( !(*b)->IsConfigured(api) )
199 return false;
201 return true;
204 int Group::GetConnectedCount() const
206 int count = 0;
207 const_iterator b = begin(), e = end();
208 for( ; b != e; ++b ) {
209 if( (*b)->GetMemberId() != -1 )
210 count++;
212 return count;
215 pst_type Group::GetSupportedSyncTypes(OpenSync::API &api) const
217 pst_type types = PST_ALL;
219 const_iterator b = begin(), e = end();
220 for( ; b != e; ++b ) {
221 types &= (*b)->GetSupportedSyncTypes(api);
224 return types;
227 std::string Group::GetAppNames() const
229 std::string names;
231 const_iterator b = begin(), e = end();
232 for( ; b != e; ++b ) {
233 std::string name = (*b)->GetAppName();
234 if( name != Config::Barry::AppName() ) {
235 if( names.size() )
236 names += ", ";
237 names += name;
241 return names;
244 OpenSync::Config::Barry& Group::GetBarryPlugin()
246 return const_cast<OpenSync::Config::Barry&> ( const_cast<const Group*> (this)->GetBarryPlugin() );
249 const OpenSync::Config::Barry& Group::GetBarryPlugin() const
251 const_iterator b = begin(), e = end();
252 for( ; b != e; ++b ) {
253 if( (*b)->GetAppName() == Config::Barry::AppName() )
254 return dynamic_cast<const OpenSync::Config::Barry&> (*(*b));
257 // not found
258 throw std::logic_error("No Barry Plugins in Group");
261 OpenSync::Config::Plugin* Group::GetNonBarryPlugin()
263 return const_cast<OpenSync::Config::Plugin*> ( const_cast<const Group*> (this)->GetNonBarryPlugin() );
266 const OpenSync::Config::Plugin* Group::GetNonBarryPlugin() const
268 const_iterator b = begin(), e = end();
269 for( ; b != e; ++b ) {
270 if( (*b)->GetAppName() != Config::Barry::AppName() )
271 return (*b).get();
274 return 0;
277 void Group::DisconnectMembers()
279 iterator b = begin(), e = end();
280 for( ; b != e; ++b ) {
281 (*b)->SetMemberId(-1);
285 void Group::Load(OpenSync::API &api, unsigned throw_mask)
287 Load(m_group_name, api, throw_mask);
290 void Group::Load(const std::string &src_group_name,
291 OpenSync::API &api,
292 unsigned throw_mask)
294 member_list_type members;
295 api.GetMembers(src_group_name, members);
297 BarryCheck(api, src_group_name, members, throw_mask);
299 member_list_type::const_iterator b = members.begin(), e = members.end();
300 for( ; b != e; ++b ) {
301 Converter &converter = api.GetConverter();
302 Converter::plugin_ptr p = converter.CreateAndLoadPlugin(*b);
303 p->SetMemberId(b->id);
305 if( p->IsUnsupported() && (throw_mask & OSCG_THROW_ON_UNSUPPORTED) ) {
306 throw LoadError(
307 string_vprintf(_C("Unsupported plugin '%s' in group '%s' and OSCG_THROW_ON_UNSUPPORTED is set."),
308 b->plugin_name.c_str(),
309 src_group_name.c_str()));
312 // everything looks ok, add the plugin to our list
313 push_back(p);
317 void Group::ResetGroupName(const std::string &new_group_name)
319 m_group_name = new_group_name;
322 void Group::AddPlugin(OpenSync::Config::Plugin *plugin)
324 plugin_ptr pp(plugin);
325 push_back(pp);
328 void Group::DeletePlugin(iterator i, OpenSync::API &api)
330 // is this plugin connected to a previously saved group config?
331 if( (*i)->GetMemberId() != -1 ) {
332 // this plugin has a member ID... only OpenSync 0.40 can
333 // delete members like that... do we have 40 support?
334 OpenSync::OpenSync40 *api40 = dynamic_cast<OpenSync::OpenSync40*> (&api);
335 if( !api40 ) {
336 // not version 0.40... can't do it capt'n!
337 throw DeleteError(_C("Cannot delete individual members from an OpenSync group with versions < 0.40."));
340 // so... we have the capability... check that the plugin
341 // name of the ID in the group matches what we think it
342 // should be
344 member_list_type members;
345 api40->GetMembers(m_group_name, members);
347 Member *m = members.Find( (*i)->GetMemberId() );
348 if( !m ) {
349 throw DeleteError(string_vprintf(_C("Tried to delete non-existent member ID %ld (%s) from group '%s'"),
350 (*i)->GetMemberId(),
351 (*i)->GetPluginName(api).c_str(),
352 m_group_name.c_str()));
355 if( m->plugin_name != (*i)->GetPluginName(api) ) {
356 throw DeleteError(string_vprintf(_C("Tried to delete member ID %ld using plugin '%s' from group '%s', but the existing member uses plugin '%s'"),
357 (*i)->GetMemberId(),
358 (*i)->GetPluginName(api).c_str(),
359 m_group_name.c_str(),
360 m->plugin_name.c_str()));
363 // so far so good... try deleting it
364 api40->DeleteMember(m_group_name, (*i)->GetMemberId());
367 // remove from our own array
368 erase(i);
371 void Group::Save(OpenSync::API &api)
373 if( GroupExists(api) ) {
374 // groups already exists, so need to confirm that our
375 // connected plugins match the existing member_ids and
376 // plugin names in the group's member list
377 if( !GroupMatchesExistingConfig(api) ) {
378 throw SaveError(string_vprintf(_C("Tried to overwrite group '%s' with a Group set that did not match in ID's and plugin names."),
379 m_group_name.c_str()));
382 else {
383 // group does not exist, so create it if needed
384 if( size() )
385 api.AddGroup(m_group_name);
388 // cycle through all plugins and save them all
389 iterator b = begin(), e = end();
390 for( ; b != e; ++b ) {
391 Config::Plugin &p = *(*b);
393 if( p.GetMemberId() == -1 ) {
394 // this plugin has never been saved yet, so
395 // add it fresh
396 long newid = api.AddMember(m_group_name,
397 p.GetPluginName(api), "");
398 p.SetMemberId(newid);
401 // save config
402 p.Save(api, m_group_name);
406 bool Group::Compare(const Group &other) const
408 // size of group equal?
409 if( size() != other.size() )
410 return false;
412 // name of group?
413 if( m_group_name != other.m_group_name )
414 return false;
416 // cycle through all plugins, searching for a match in other
417 const_iterator i = begin();
418 for( ; i != end(); ++i ) {
419 bool sametype, equal;
420 bool match = false;
422 // search other for a match
423 const_iterator oi = other.begin();
424 for( ; oi != other.end(); ++oi ) {
425 if( (match = (*i)->Compare(*(*oi), sametype, equal)) )
426 break;
429 if( !match )
430 return false;
433 return true;
436 Group::group_ptr Group::Clone() const
438 group_ptr g( new Group(m_group_name) );
440 // clone all plugins
441 const_iterator b = begin(), e = end();
442 for( ; b != e; ++b ) {
443 plugin_ptr p( (*b)->Clone() );
444 g->push_back(p);
447 return g;
450 }} // namespace OpenSync::Config