3 /// Class which detects a set of available or known devices
4 /// in an opensync-able system.
8 Copyright (C) 2009-2013, 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.
25 #include <sys/types.h>
33 using namespace Barry
;
35 namespace OpenSync
{ namespace Config
{
37 //////////////////////////////////////////////////////////////////////////////
38 // Unsupported config class
40 std::string
Unsupported::AppName()
42 return _C("Unsupported");
46 //////////////////////////////////////////////////////////////////////////////
49 Barry::Barry(const ::Barry::Pin
&pin
)
54 throw std::logic_error(_C("Barry config must have valid pin number."));
57 Barry::Barry(Converter
*load_converter
, const Member
&member
)
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
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 //////////////////////////////////////////////////////////////////////////////
82 Group::Group(const std::string
&group_name
,
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
,
101 if( ! (throw_mask
& (OSCG_THROW_ON_NO_BARRY
| OSCG_THROW_ON_MULTIPLE_BARRIES
) ) )
102 return; // nothing to do
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
)
112 if( found
== 0 && (throw_mask
& OSCG_THROW_ON_NO_BARRY
) ) {
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
) ) {
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
136 // check totals match
137 if( (unsigned) GetConnectedCount() != members
.size() ) {
138 barryverbose("Connected count of " << GetConnectedCount() << " does not match member count of " << members
.size());
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 )
149 Member
*m
= members
.Find( (*ci
)->GetMemberId() );
151 barryverbose("Can't match member ID: " << (*ci
)->GetMemberId() );
155 if( m
->plugin_name
!= (*ci
)->GetPluginName(api
) ) {
156 barryverbose("Plugin names don't match: "
157 << m
->plugin_name
<< ", "
158 << (*ci
)->GetPluginName(api
));
166 bool Group::HasUnsupportedPlugins() const
168 const_iterator b
= begin(), e
= end();
169 for( ; b
!= e
; ++b
) {
170 if( (*b
)->IsUnsupported() )
176 bool Group::HasBarryPlugins() const
178 const_iterator b
= begin(), e
= end();
179 for( ; b
!= e
; ++b
) {
180 if( (*b
)->GetAppName() == Config::Barry::AppName() )
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
) )
204 int Group::GetConnectedCount() const
207 const_iterator b
= begin(), e
= end();
208 for( ; b
!= e
; ++b
) {
209 if( (*b
)->GetMemberId() != -1 )
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
);
227 std::string
Group::GetAppNames() const
231 const_iterator b
= begin(), e
= end();
232 for( ; b
!= e
; ++b
) {
233 std::string name
= (*b
)->GetAppName();
234 if( name
!= Config::Barry::AppName() ) {
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
));
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() )
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
,
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
) ) {
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
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
);
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
);
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
344 member_list_type members
;
345 api40
->GetMembers(m_group_name
, members
);
347 Member
*m
= members
.Find( (*i
)->GetMemberId() );
349 throw DeleteError(string_vprintf(_C("Tried to delete non-existent member ID %ld (%s) from group '%s'"),
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'"),
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
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()));
383 // group does not exist, so create it if needed
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
396 long newid
= api
.AddMember(m_group_name
,
397 p
.GetPluginName(api
), "");
398 p
.SetMemberId(newid
);
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() )
413 if( m_group_name
!= other
.m_group_name
)
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
;
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
)) )
436 Group::group_ptr
Group::Clone() const
438 group_ptr
g( new Group(m_group_name
) );
441 const_iterator b
= begin(), e
= end();
442 for( ; b
!= e
; ++b
) {
443 plugin_ptr
p( (*b
)->Clone() );
450 }} // namespace OpenSync::Config