3 /// Class which detects a set of available or known devices
4 /// in an opensync-able system.
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.
25 #include <sys/types.h>
33 namespace OpenSync
{ namespace Config
{
35 //////////////////////////////////////////////////////////////////////////////
38 Group::Group(const std::string
&group_name
,
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
,
57 if( ! (throw_mask
& (OSCG_THROW_ON_NO_BARRY
| OSCG_THROW_ON_MULTIPLE_BARRIES
) ) )
58 return; // nothing to do
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
)
68 if( found
== 0 && (throw_mask
& OSCG_THROW_ON_NO_BARRY
) ) {
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
) ) {
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
95 if( (unsigned) GetConnectedCount() != members
.size() ) {
96 barryverbose("Connected count of " << GetConnectedCount() << " does not match member count of " << members
.size());
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 )
107 Member
*m
= members
.Find( (*ci
)->GetMemberId() );
109 barryverbose("Can't match member ID: " << (*ci
)->GetMemberId() );
113 if( m
->plugin_name
!= (*ci
)->GetPluginName(api
) ) {
114 barryverbose("Plugin names don't match: "
115 << m
->plugin_name
<< ", "
116 << (*ci
)->GetPluginName(api
));
124 bool Group::HasUnsupportedPlugins() const
126 const_iterator b
= begin(), e
= end();
127 for( ; b
!= e
; ++b
) {
128 if( (*b
)->IsUnsupported() )
134 bool Group::HasBarryPlugins() const
136 const_iterator b
= begin(), e
= end();
137 for( ; b
!= e
; ++b
) {
138 if( (*b
)->GetAppName() == Config::Barry::AppName() )
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
) )
162 int Group::GetConnectedCount() const
165 const_iterator b
= begin(), e
= end();
166 for( ; b
!= e
; ++b
) {
167 if( (*b
)->GetMemberId() != -1 )
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
);
185 std::string
Group::GetAppNames() const
189 const_iterator b
= begin(), e
= end();
190 for( ; b
!= e
; ++b
) {
191 std::string name
= (*b
)->GetAppName();
192 if( name
!= Config::Barry::AppName() ) {
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
));
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() )
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
,
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
) ) {
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
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
);
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
);
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
301 member_list_type members
;
302 api40
->GetMembers(m_group_name
, members
);
304 Member
*m
= members
.Find( (*i
)->GetMemberId() );
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
) ) {
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
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
) ) {
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());
338 // group does not exist, so create it if needed
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
351 long newid
= api
.AddMember(m_group_name
,
352 p
.GetPluginName(api
), "");
353 p
.SetMemberId(newid
);
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() )
368 if( m_group_name
!= other
.m_group_name
)
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
;
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
)) )
391 Group::group_ptr
Group::Clone() const
393 group_ptr
g( new Group(m_group_name
) );
396 const_iterator b
= begin(), e
= end();
397 for( ; b
!= e
; ++b
) {
398 plugin_ptr
p( (*b
)->Clone() );
405 }} // namespace OpenSync::Config