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>
34 namespace OpenSync
{ namespace Config
{
36 //////////////////////////////////////////////////////////////////////////////
37 // Unsupported config class
39 std::string
Unsupported::AppName()
41 return _C("Unsupported");
45 //////////////////////////////////////////////////////////////////////////////
48 Barry::Barry(const ::Barry::Pin
&pin
)
53 throw std::logic_error(_C("Barry config must have valid pin number."));
56 Barry::Barry(Converter
*load_converter
, const Member
&member
)
59 load_converter
->Load(*this, member
);
61 // check that the loaded pin is valid... if not, it is
62 // likely safe to assume that something is horribly wrong.
63 // in the case where the Application wishes to add a new
64 // barry plugin, it should use the Pin constructor.
65 // if you *really* need to try to salvage an old
66 // corrupt config, you can always do the
67 // converter->Load(barry_obj) manually, and pick out
70 if( !m_pin
.Valid() ) {
71 std::ostringstream oss
;
72 oss
<< _C("Unable to load pin number from Barry plugin config. Consider this group corrupt, or not fully configured: ") << member
;
73 throw LoadError(oss
.str());
78 //////////////////////////////////////////////////////////////////////////////
81 Group::Group(const std::string
&group_name
,
84 : m_group_name(group_name
)
86 Load(api
, throw_mask
);
89 Group::Group(const std::string
&group_name
)
90 : m_group_name(group_name
)
94 // Checks for OSCG_THROW_ON_NO_BARRY and OSCG_THROW_ON_MULTIPLE_BARRIES
95 void Group::BarryCheck(OpenSync::API
&api
,
96 const std::string
&group_name
,
97 const member_list_type
&members
,
100 if( ! (throw_mask
& (OSCG_THROW_ON_NO_BARRY
| OSCG_THROW_ON_MULTIPLE_BARRIES
) ) )
101 return; // nothing to do
104 std::string barry_name
= Config::Barry::PluginName(api
);
105 member_list_type::const_iterator b
= members
.begin(), e
= members
.end();
106 for( ; b
!= e
; ++b
) {
107 if( b
->plugin_name
== barry_name
)
111 if( found
== 0 && (throw_mask
& OSCG_THROW_ON_NO_BARRY
) ) {
113 oss
<< _C("No Barry plugins found in group '") << group_name
<< _C("' and OSCG_THROW_ON_NO_BARRY is set.");
114 throw LoadError(oss
.str());
117 if( found
> 1 && (throw_mask
& OSCG_THROW_ON_MULTIPLE_BARRIES
) ) {
119 oss
<< _C("Found ") << found
<< _C(" Barry plugins in group '") << group_name
<< _C("' and OSCG_THROW_ON_MULTIPLE_BARRIES is set.");
120 throw LoadError(oss
.str());
124 bool Group::GroupMatchesExistingConfig(OpenSync::API
&api
)
126 member_list_type members
;
127 api
.GetMembers(m_group_name
, members
);
129 // what needs to match:
131 // - number of connected Config::Plugin objects in our
132 // list must match number of members in config
133 // - each member ID must match along with the plugin_name
137 // check totals match
138 if( (unsigned) GetConnectedCount() != members
.size() ) {
139 barryverbose(_C("Connected count of ") << GetConnectedCount() << _C(" does not match member count of ") << members
.size());
143 // cycle through our own vector, matching against each member_id
144 // in the members list
145 const_iterator ci
= begin(), ce
= end();
146 for( ; ci
!= ce
; ++ci
) {
147 if( (*ci
)->GetMemberId() == -1 )
150 Member
*m
= members
.Find( (*ci
)->GetMemberId() );
152 barryverbose(_C("Can't match member ID: ") << (*ci
)->GetMemberId() );
156 if( m
->plugin_name
!= (*ci
)->GetPluginName(api
) ) {
157 barryverbose(_C("Plugin names don't match: ")
158 << m
->plugin_name
<< ", "
159 << (*ci
)->GetPluginName(api
));
167 bool Group::HasUnsupportedPlugins() const
169 const_iterator b
= begin(), e
= end();
170 for( ; b
!= e
; ++b
) {
171 if( (*b
)->IsUnsupported() )
177 bool Group::HasBarryPlugins() const
179 const_iterator b
= begin(), e
= end();
180 for( ; b
!= e
; ++b
) {
181 if( (*b
)->GetAppName() == Config::Barry::AppName() )
187 bool Group::GroupExists(OpenSync::API
&api
) const
189 // does m_group_name exist in the API list?
190 string_list_type groups
;
191 api
.GetGroupNames(groups
);
192 return std::find(groups
.begin(), groups
.end(), m_group_name
) != groups
.end();
195 bool Group::AllConfigured(OpenSync::API
&api
) const
197 const_iterator b
= begin(), e
= end();
198 for( ; b
!= e
; ++b
) {
199 if( !(*b
)->IsConfigured(api
) )
205 int Group::GetConnectedCount() const
208 const_iterator b
= begin(), e
= end();
209 for( ; b
!= e
; ++b
) {
210 if( (*b
)->GetMemberId() != -1 )
216 pst_type
Group::GetSupportedSyncTypes(OpenSync::API
&api
) const
218 pst_type types
= PST_ALL
;
220 const_iterator b
= begin(), e
= end();
221 for( ; b
!= e
; ++b
) {
222 types
&= (*b
)->GetSupportedSyncTypes(api
);
228 std::string
Group::GetAppNames() const
232 const_iterator b
= begin(), e
= end();
233 for( ; b
!= e
; ++b
) {
234 std::string name
= (*b
)->GetAppName();
235 if( name
!= Config::Barry::AppName() ) {
245 OpenSync::Config::Barry
& Group::GetBarryPlugin()
247 return const_cast<OpenSync::Config::Barry
&> ( const_cast<const Group
*> (this)->GetBarryPlugin() );
250 const OpenSync::Config::Barry
& Group::GetBarryPlugin() const
252 const_iterator b
= begin(), e
= end();
253 for( ; b
!= e
; ++b
) {
254 if( (*b
)->GetAppName() == Config::Barry::AppName() )
255 return dynamic_cast<const OpenSync::Config::Barry
&> (*(*b
));
259 throw std::logic_error("No Barry Plugins in Group");
262 OpenSync::Config::Plugin
* Group::GetNonBarryPlugin()
264 return const_cast<OpenSync::Config::Plugin
*> ( const_cast<const Group
*> (this)->GetNonBarryPlugin() );
267 const OpenSync::Config::Plugin
* Group::GetNonBarryPlugin() const
269 const_iterator b
= begin(), e
= end();
270 for( ; b
!= e
; ++b
) {
271 if( (*b
)->GetAppName() != Config::Barry::AppName() )
278 void Group::DisconnectMembers()
280 iterator b
= begin(), e
= end();
281 for( ; b
!= e
; ++b
) {
282 (*b
)->SetMemberId(-1);
286 void Group::Load(OpenSync::API
&api
, unsigned throw_mask
)
288 Load(m_group_name
, api
, throw_mask
);
291 void Group::Load(const std::string
&src_group_name
,
295 member_list_type members
;
296 api
.GetMembers(src_group_name
, members
);
298 BarryCheck(api
, src_group_name
, members
, throw_mask
);
300 member_list_type::const_iterator b
= members
.begin(), e
= members
.end();
301 for( ; b
!= e
; ++b
) {
302 Converter
&converter
= api
.GetConverter();
303 Converter::plugin_ptr p
= converter
.CreateAndLoadPlugin(*b
);
304 p
->SetMemberId(b
->id
);
306 if( p
->IsUnsupported() && (throw_mask
& OSCG_THROW_ON_UNSUPPORTED
) ) {
308 oss
<< _C("Unsupported plugin '") << b
->plugin_name
<< _C("' in group '") << src_group_name
<< _C("' and OSCG_THROW_ON_UNSUPPORTED is set.");
309 throw LoadError(oss
.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() );
350 oss
<< _C("Tried to delete non-existent member ID ") << (*i
)->GetMemberId() << " (" << (*i
)->GetPluginName(api
) << ") " << _C("from group") << "'" << m_group_name
<< "'";
351 throw DeleteError(oss
.str());
354 if( m
->plugin_name
!= (*i
)->GetPluginName(api
) ) {
356 oss
<< _C("Tried to delete member ID ") << (*i
)->GetMemberId() << _C(" using plugin '") << (*i
)->GetPluginName(api
) << _C("' from group '") << m_group_name
<< _C("', but the existing member uses plugin") << "'" << m
->plugin_name
<< "'";
357 throw DeleteError(oss
.str());
360 // so far so good... try deleting it
361 api40
->DeleteMember(m_group_name
, (*i
)->GetMemberId());
364 // remove from our own array
368 void Group::Save(OpenSync::API
&api
)
370 if( GroupExists(api
) ) {
371 // groups already exists, so need to confirm that our
372 // connected plugins match the existing member_ids and
373 // plugin names in the group's member list
374 if( !GroupMatchesExistingConfig(api
) ) {
376 oss
<< _C("Tried to overwrite group '") << m_group_name
<< _C("' with a Group set that did not match in ID's and plugin names.");
377 throw SaveError(oss
.str());
381 // group does not exist, so create it if needed
383 api
.AddGroup(m_group_name
);
386 // cycle through all plugins and save them all
387 iterator b
= begin(), e
= end();
388 for( ; b
!= e
; ++b
) {
389 Config::Plugin
&p
= *(*b
);
391 if( p
.GetMemberId() == -1 ) {
392 // this plugin has never been saved yet, so
394 long newid
= api
.AddMember(m_group_name
,
395 p
.GetPluginName(api
), "");
396 p
.SetMemberId(newid
);
400 p
.Save(api
, m_group_name
);
404 bool Group::Compare(const Group
&other
) const
406 // size of group equal?
407 if( size() != other
.size() )
411 if( m_group_name
!= other
.m_group_name
)
414 // cycle through all plugins, searching for a match in other
415 const_iterator i
= begin();
416 for( ; i
!= end(); ++i
) {
417 bool sametype
, equal
;
420 // search other for a match
421 const_iterator oi
= other
.begin();
422 for( ; oi
!= other
.end(); ++oi
) {
423 if( (match
= (*i
)->Compare(*(*oi
), sametype
, equal
)) )
434 Group::group_ptr
Group::Clone() const
436 group_ptr
g( new Group(m_group_name
) );
439 const_iterator b
= begin(), e
= end();
440 for( ; b
!= e
; ++b
) {
441 plugin_ptr
p( (*b
)->Clone() );
448 }} // namespace OpenSync::Config