lib: added implicit ctor converter from DatabaseDatabase to DBListType
[barry/progweb.git] / desktop / src / osconfig.cc
blob2e180f87c49ff90344880c25b095b85f7484cbb1
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>
31 using namespace std;
33 namespace OpenSync { namespace Config {
35 //////////////////////////////////////////////////////////////////////////////
36 // Group class
38 Group::Group(const std::string &group_name,
39 OpenSync::API &api,
40 unsigned throw_mask)
41 : m_group_name(group_name)
43 Load(api, throw_mask);
46 Group::Group(const std::string &group_name)
47 : m_group_name(group_name)
51 // Checks for OSCG_THROW_ON_NO_BARRY and OSCG_THROW_ON_MULTIPLE_BARRIES
52 void Group::BarryCheck(OpenSync::API &api,
53 const std::string &group_name,
54 const member_list_type &members,
55 unsigned throw_mask)
57 if( ! (throw_mask & (OSCG_THROW_ON_NO_BARRY | OSCG_THROW_ON_MULTIPLE_BARRIES) ) )
58 return; // nothing to do
60 int found = 0;
61 std::string barry_name = Config::Barry::PluginName(api);
62 member_list_type::const_iterator b = members.begin(), e = members.end();
63 for( ; b != e; ++b ) {
64 if( b->plugin_name == barry_name )
65 found++;
68 if( found == 0 && (throw_mask & OSCG_THROW_ON_NO_BARRY) ) {
69 ostringstream oss;
70 oss << "No Barry plugins found in group '" << group_name << "' and OSCG_THROW_ON_NO_BARRY is set.";
71 throw LoadError(oss.str());
74 if( found > 1 && (throw_mask & OSCG_THROW_ON_MULTIPLE_BARRIES) ) {
75 ostringstream oss;
76 oss << "Found " << found << " Barry plugins in group '" << group_name << "' and OSCG_THROW_ON_MULTIPLE_BARRIES is set.";
77 throw LoadError(oss.str());
81 bool Group::GroupMatchesExistingConfig(OpenSync::API &api)
83 member_list_type members;
84 api.GetMembers(m_group_name, members);
86 // what needs to match:
88 // - number of connected Config::Plugin objects in our
89 // list must match number of members in config
90 // - each member ID must match along with the plugin_name
91 // of each member
94 // check totals match
95 if( (unsigned) GetConnectedCount() != members.size() ) {
96 barryverbose("Connected count of " << GetConnectedCount() << " does not match member count of " << members.size());
97 return false;
100 // cycle through our own vector, matching against each member_id
101 // in the members list
102 const_iterator ci = begin(), ce = end();
103 for( ; ci != ce; ++ci ) {
104 if( (*ci)->GetMemberId() == -1 )
105 continue;
107 Member *m = members.Find( (*ci)->GetMemberId() );
108 if( !m ) {
109 barryverbose("Can't match member ID: " << (*ci)->GetMemberId() );
110 return false;
113 if( m->plugin_name != (*ci)->GetPluginName(api) ) {
114 barryverbose("Plugin names don't match: "
115 << m->plugin_name << ", "
116 << (*ci)->GetPluginName(api));
117 return false;
121 return true;
124 bool Group::HasUnsupportedPlugins() const
126 const_iterator b = begin(), e = end();
127 for( ; b != e; ++b ) {
128 if( (*b)->IsUnsupported() )
129 return true;
131 return false;
134 bool Group::HasBarryPlugins() const
136 const_iterator b = begin(), e = end();
137 for( ; b != e; ++b ) {
138 if( (*b)->GetAppName() == Config::Barry::AppName() )
139 return true;
141 return false;
144 bool Group::GroupExists(OpenSync::API &api) const
146 // does m_group_name exist in the API list?
147 string_list_type groups;
148 api.GetGroupNames(groups);
149 return std::find(groups.begin(), groups.end(), m_group_name) != groups.end();
152 bool Group::AllConfigured(OpenSync::API &api) const
154 const_iterator b = begin(), e = end();
155 for( ; b != e; ++b ) {
156 if( !(*b)->IsConfigured(api) )
157 return false;
159 return true;
162 int Group::GetConnectedCount() const
164 int count = 0;
165 const_iterator b = begin(), e = end();
166 for( ; b != e; ++b ) {
167 if( (*b)->GetMemberId() != -1 )
168 count++;
170 return count;
173 pst_type Group::GetSupportedSyncTypes(OpenSync::API &api) const
175 pst_type types = PST_ALL;
177 const_iterator b = begin(), e = end();
178 for( ; b != e; ++b ) {
179 types &= (*b)->GetSupportedSyncTypes(api);
182 return types;
185 std::string Group::GetAppNames() const
187 std::string names;
189 const_iterator b = begin(), e = end();
190 for( ; b != e; ++b ) {
191 std::string name = (*b)->GetAppName();
192 if( name != Config::Barry::AppName() ) {
193 if( names.size() )
194 names += ", ";
195 names += name;
199 return names;
202 OpenSync::Config::Barry& Group::GetBarryPlugin()
204 return const_cast<OpenSync::Config::Barry&> ( const_cast<const Group*> (this)->GetBarryPlugin() );
207 const OpenSync::Config::Barry& Group::GetBarryPlugin() const
209 const_iterator b = begin(), e = end();
210 for( ; b != e; ++b ) {
211 if( (*b)->GetAppName() == Config::Barry::AppName() )
212 return dynamic_cast<const OpenSync::Config::Barry&> (*(*b));
215 // not found
216 throw std::logic_error("No Barry Plugins in Group");
219 OpenSync::Config::Plugin* Group::GetNonBarryPlugin()
221 return const_cast<OpenSync::Config::Plugin*> ( const_cast<const Group*> (this)->GetNonBarryPlugin() );
224 const OpenSync::Config::Plugin* Group::GetNonBarryPlugin() const
226 const_iterator b = begin(), e = end();
227 for( ; b != e; ++b ) {
228 if( (*b)->GetAppName() != Config::Barry::AppName() )
229 return (*b).get();
232 return 0;
235 void Group::DisconnectMembers()
237 iterator b = begin(), e = end();
238 for( ; b != e; ++b ) {
239 (*b)->SetMemberId(-1);
243 void Group::Load(OpenSync::API &api, unsigned throw_mask)
245 Load(m_group_name, api, throw_mask);
248 void Group::Load(const std::string &src_group_name,
249 OpenSync::API &api,
250 unsigned throw_mask)
252 member_list_type members;
253 api.GetMembers(src_group_name, members);
255 BarryCheck(api, src_group_name, members, throw_mask);
257 member_list_type::const_iterator b = members.begin(), e = members.end();
258 for( ; b != e; ++b ) {
259 Converter &converter = api.GetConverter();
260 Converter::plugin_ptr p = converter.CreateAndLoadPlugin(*b);
261 p->SetMemberId(b->id);
263 if( p->IsUnsupported() && (throw_mask & OSCG_THROW_ON_UNSUPPORTED) ) {
264 ostringstream oss;
265 oss << "Unsupported plugin '" << b->plugin_name << "' in group '" << src_group_name << "' and OSCG_THROW_ON_UNSUPPORTED is set.";
266 throw LoadError(oss.str());
269 // everything looks ok, add the plugin to our list
270 push_back(p);
274 void Group::ResetGroupName(const std::string &new_group_name)
276 m_group_name = new_group_name;
279 void Group::AddPlugin(OpenSync::Config::Plugin *plugin)
281 plugin_ptr pp(plugin);
282 push_back(pp);
285 void Group::DeletePlugin(iterator i, OpenSync::API &api)
287 // is this plugin connected to a previously saved group config?
288 if( (*i)->GetMemberId() != -1 ) {
289 // this plugin has a member ID... only OpenSync 0.40 can
290 // delete members like that... do we have 40 support?
291 OpenSync::OpenSync40 *api40 = dynamic_cast<OpenSync::OpenSync40*> (&api);
292 if( !api40 ) {
293 // not version 0.40... can't do it capt'n!
294 throw DeleteError("Cannot delete individual members from an OpenSync group with versions < 0.40.");
297 // so... we have the capability... check that the plugin
298 // name of the ID in the group matches what we think it
299 // should be
301 member_list_type members;
302 api40->GetMembers(m_group_name, members);
304 Member *m = members.Find( (*i)->GetMemberId() );
305 if( !m ) {
306 ostringstream oss;
307 oss << "Tried to delete non-existent member ID " << (*i)->GetMemberId() << " (" << (*i)->GetPluginName(api) << ") from group '" << m_group_name << "'";
308 throw DeleteError(oss.str());
311 if( m->plugin_name != (*i)->GetPluginName(api) ) {
312 ostringstream oss;
313 oss << "Tried to delete member ID " << (*i)->GetMemberId() << " using plugin '" << (*i)->GetPluginName(api) << "' from group '" << m_group_name << "', but the existing member uses plugin '" << m->plugin_name << "'";
314 throw DeleteError(oss.str());
317 // so far so good... try deleting it
318 api40->DeleteMember(m_group_name, (*i)->GetMemberId());
321 // remove from our own array
322 erase(i);
325 void Group::Save(OpenSync::API &api)
327 if( GroupExists(api) ) {
328 // groups already exists, so need to confirm that our
329 // connected plugins match the existing member_ids and
330 // plugin names in the group's member list
331 if( !GroupMatchesExistingConfig(api) ) {
332 ostringstream oss;
333 oss << "Tried to overwrite group '" << m_group_name << "' with a Group set that did not match in ID's and plugin names.";
334 throw SaveError(oss.str());
337 else {
338 // group does not exist, so create it if needed
339 if( size() )
340 api.AddGroup(m_group_name);
343 // cycle through all plugins and save them all
344 iterator b = begin(), e = end();
345 for( ; b != e; ++b ) {
346 Config::Plugin &p = *(*b);
348 if( p.GetMemberId() == -1 ) {
349 // this plugin has never been saved yet, so
350 // add it fresh
351 long newid = api.AddMember(m_group_name,
352 p.GetPluginName(api), "");
353 p.SetMemberId(newid);
356 // save config
357 p.Save(api, m_group_name);
361 bool Group::Compare(const Group &other) const
363 // size of group equal?
364 if( size() != other.size() )
365 return false;
367 // name of group?
368 if( m_group_name != other.m_group_name )
369 return false;
371 // cycle through all plugins, searching for a match in other
372 const_iterator i = begin();
373 for( ; i != end(); ++i ) {
374 bool sametype, equal;
375 bool match = false;
377 // search other for a match
378 const_iterator oi = other.begin();
379 for( ; oi != other.end(); ++oi ) {
380 if( (match = (*i)->Compare(*(*oi), sametype, equal)) )
381 break;
384 if( !match )
385 return false;
388 return true;
391 Group::group_ptr Group::Clone() const
393 group_ptr g( new Group(m_group_name) );
395 // clone all plugins
396 const_iterator b = begin(), e = end();
397 for( ; b != e; ++b ) {
398 plugin_ptr p( (*b)->Clone() );
399 g->push_back(p);
402 return g;
405 }} // namespace OpenSync::Config