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 string_vprintf(_C("No Barry plugins found in group '%s' and OSCG_THROW_ON_NO_BARRY is set."), group_name
.c_str()));
116 if( found
> 1 && (throw_mask
& OSCG_THROW_ON_MULTIPLE_BARRIES
) ) {
118 string_vprintf(_C("Found %d Barry plugins in group '%s' and OSCG_THROW_ON_MULTIPLE_BARRIES is set."), found
, group_name
.c_str()));
122 bool Group::GroupMatchesExistingConfig(OpenSync::API
&api
)
124 member_list_type members
;
125 api
.GetMembers(m_group_name
, members
);
127 // what needs to match:
129 // - number of connected Config::Plugin objects in our
130 // list must match number of members in config
131 // - each member ID must match along with the plugin_name
135 // check totals match
136 if( (unsigned) GetConnectedCount() != members
.size() ) {
137 barryverbose("Connected count of " << GetConnectedCount() << " does not match member count of " << members
.size());
141 // cycle through our own vector, matching against each member_id
142 // in the members list
143 const_iterator ci
= begin(), ce
= end();
144 for( ; ci
!= ce
; ++ci
) {
145 if( (*ci
)->GetMemberId() == -1 )
148 Member
*m
= members
.Find( (*ci
)->GetMemberId() );
150 barryverbose("Can't match member ID: " << (*ci
)->GetMemberId() );
154 if( m
->plugin_name
!= (*ci
)->GetPluginName(api
) ) {
155 barryverbose("Plugin names don't match: "
156 << m
->plugin_name
<< ", "
157 << (*ci
)->GetPluginName(api
));
165 bool Group::HasUnsupportedPlugins() const
167 const_iterator b
= begin(), e
= end();
168 for( ; b
!= e
; ++b
) {
169 if( (*b
)->IsUnsupported() )
175 bool Group::HasBarryPlugins() const
177 const_iterator b
= begin(), e
= end();
178 for( ; b
!= e
; ++b
) {
179 if( (*b
)->GetAppName() == Config::Barry::AppName() )
185 bool Group::GroupExists(OpenSync::API
&api
) const
187 // does m_group_name exist in the API list?
188 string_list_type groups
;
189 api
.GetGroupNames(groups
);
190 return std::find(groups
.begin(), groups
.end(), m_group_name
) != groups
.end();
193 bool Group::AllConfigured(OpenSync::API
&api
) const
195 const_iterator b
= begin(), e
= end();
196 for( ; b
!= e
; ++b
) {
197 if( !(*b
)->IsConfigured(api
) )
203 int Group::GetConnectedCount() const
206 const_iterator b
= begin(), e
= end();
207 for( ; b
!= e
; ++b
) {
208 if( (*b
)->GetMemberId() != -1 )
214 pst_type
Group::GetSupportedSyncTypes(OpenSync::API
&api
) const
216 pst_type types
= PST_ALL
;
218 const_iterator b
= begin(), e
= end();
219 for( ; b
!= e
; ++b
) {
220 types
&= (*b
)->GetSupportedSyncTypes(api
);
226 std::string
Group::GetAppNames() const
230 const_iterator b
= begin(), e
= end();
231 for( ; b
!= e
; ++b
) {
232 std::string name
= (*b
)->GetAppName();
233 if( name
!= Config::Barry::AppName() ) {
243 OpenSync::Config::Barry
& Group::GetBarryPlugin()
245 return const_cast<OpenSync::Config::Barry
&> ( const_cast<const Group
*> (this)->GetBarryPlugin() );
248 const OpenSync::Config::Barry
& Group::GetBarryPlugin() const
250 const_iterator b
= begin(), e
= end();
251 for( ; b
!= e
; ++b
) {
252 if( (*b
)->GetAppName() == Config::Barry::AppName() )
253 return dynamic_cast<const OpenSync::Config::Barry
&> (*(*b
));
257 throw std::logic_error("No Barry Plugins in Group");
260 OpenSync::Config::Plugin
* Group::GetNonBarryPlugin()
262 return const_cast<OpenSync::Config::Plugin
*> ( const_cast<const Group
*> (this)->GetNonBarryPlugin() );
265 const OpenSync::Config::Plugin
* Group::GetNonBarryPlugin() const
267 const_iterator b
= begin(), e
= end();
268 for( ; b
!= e
; ++b
) {
269 if( (*b
)->GetAppName() != Config::Barry::AppName() )
276 void Group::DisconnectMembers()
278 iterator b
= begin(), e
= end();
279 for( ; b
!= e
; ++b
) {
280 (*b
)->SetMemberId(-1);
284 void Group::Load(OpenSync::API
&api
, unsigned throw_mask
)
286 Load(m_group_name
, api
, throw_mask
);
289 void Group::Load(const std::string
&src_group_name
,
293 member_list_type members
;
294 api
.GetMembers(src_group_name
, members
);
296 BarryCheck(api
, src_group_name
, members
, throw_mask
);
298 member_list_type::const_iterator b
= members
.begin(), e
= members
.end();
299 for( ; b
!= e
; ++b
) {
300 Converter
&converter
= api
.GetConverter();
301 Converter::plugin_ptr p
= converter
.CreateAndLoadPlugin(*b
);
302 p
->SetMemberId(b
->id
);
304 if( p
->IsUnsupported() && (throw_mask
& OSCG_THROW_ON_UNSUPPORTED
) ) {
306 string_vprintf(_C("Unsupported plugin '%s' in group '%s' and OSCG_THROW_ON_UNSUPPORTED is set."),
307 b
->plugin_name
.c_str(),
308 src_group_name
.c_str()));
311 // everything looks ok, add the plugin to our list
316 void Group::ResetGroupName(const std::string
&new_group_name
)
318 m_group_name
= new_group_name
;
321 void Group::AddPlugin(OpenSync::Config::Plugin
*plugin
)
323 plugin_ptr
pp(plugin
);
327 void Group::DeletePlugin(iterator i
, OpenSync::API
&api
)
329 // is this plugin connected to a previously saved group config?
330 if( (*i
)->GetMemberId() != -1 ) {
331 // this plugin has a member ID... only OpenSync 0.40 can
332 // delete members like that... do we have 40 support?
333 OpenSync::OpenSync40
*api40
= dynamic_cast<OpenSync::OpenSync40
*> (&api
);
335 // not version 0.40... can't do it capt'n!
336 throw DeleteError(_C("Cannot delete individual members from an OpenSync group with versions < 0.40."));
339 // so... we have the capability... check that the plugin
340 // name of the ID in the group matches what we think it
343 member_list_type members
;
344 api40
->GetMembers(m_group_name
, members
);
346 Member
*m
= members
.Find( (*i
)->GetMemberId() );
348 throw DeleteError(string_vprintf(_C("Tried to delete non-existent member ID %ld (%s) from group '%s'"),
350 (*i
)->GetPluginName(api
).c_str(),
351 m_group_name
.c_str()));
354 if( m
->plugin_name
!= (*i
)->GetPluginName(api
) ) {
355 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
)->GetPluginName(api
).c_str(),
358 m_group_name
.c_str(),
359 m
->plugin_name
.c_str()));
362 // so far so good... try deleting it
363 api40
->DeleteMember(m_group_name
, (*i
)->GetMemberId());
366 // remove from our own array
370 void Group::Save(OpenSync::API
&api
)
372 if( GroupExists(api
) ) {
373 // groups already exists, so need to confirm that our
374 // connected plugins match the existing member_ids and
375 // plugin names in the group's member list
376 if( !GroupMatchesExistingConfig(api
) ) {
377 throw SaveError(string_vprintf(_C("Tried to overwrite group '%s' with a Group set that did not match in ID's and plugin names."),
378 m_group_name
.c_str()));
382 // group does not exist, so create it if needed
384 api
.AddGroup(m_group_name
);
387 // cycle through all plugins and save them all
388 iterator b
= begin(), e
= end();
389 for( ; b
!= e
; ++b
) {
390 Config::Plugin
&p
= *(*b
);
392 if( p
.GetMemberId() == -1 ) {
393 // this plugin has never been saved yet, so
395 long newid
= api
.AddMember(m_group_name
,
396 p
.GetPluginName(api
), "");
397 p
.SetMemberId(newid
);
401 p
.Save(api
, m_group_name
);
405 bool Group::Compare(const Group
&other
) const
407 // size of group equal?
408 if( size() != other
.size() )
412 if( m_group_name
!= other
.m_group_name
)
415 // cycle through all plugins, searching for a match in other
416 const_iterator i
= begin();
417 for( ; i
!= end(); ++i
) {
418 bool sametype
, equal
;
421 // search other for a match
422 const_iterator oi
= other
.begin();
423 for( ; oi
!= other
.end(); ++oi
) {
424 if( (match
= (*i
)->Compare(*(*oi
), sametype
, equal
)) )
435 Group::group_ptr
Group::Clone() const
437 group_ptr
g( new Group(m_group_name
) );
440 const_iterator b
= begin(), e
= end();
441 for( ; b
!= e
; ++b
) {
442 plugin_ptr
p( (*b
)->Clone() );
449 }} // namespace OpenSync::Config