Adding a hand test to validate EnsureChannel, fixing the ensure channel issues
[theonering] / src / tp / channelmanager.py
1 # telepathy-python - Base classes defining the interfaces of the Telepathy framework
2 #
3 # Copyright (C) 2009 Collabora Limited
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19 from telepathy.errors import NotImplemented
20
21 from telepathy.interfaces import (CHANNEL_INTERFACE,
22                                  CHANNEL_TYPE_CONTACT_LIST,
23                                  CHANNEL_TYPE_TEXT)
24
25 class ChannelManager(object):
26
27     def __init__(self, connection):
28         self._conn = connection
29
30         self._requestable_channel_classes = dict()
31         self._channels = dict()
32         self._fixed_properties = dict()
33         self._available_properties = dict()
34
35     def close(self):
36         for channel_type in self._requestable_channel_classes:
37             for channel in self._channels[channel_type].values():
38                 if channel._type == CHANNEL_TYPE_CONTACT_LIST:
39                     channel.remove_from_connection()
40                 else:
41                     channel.Close()
42
43     def remove_channel(self, channel):
44         for channel_type in self._requestable_channel_classes:
45             for handle, chan in self._channels[channel_type].items():
46                 if channel == chan:
47                     del self._channels[channel_type][handle]
48
49     def _get_type_requested_handle(self, props):
50         type = props[CHANNEL_INTERFACE + '.ChannelType']
51         requested = props[CHANNEL_INTERFACE + '.Requested']
52         target_handle = int(props[CHANNEL_INTERFACE + '.TargetHandle'])
53         target_handle_type = int(props[CHANNEL_INTERFACE + '.TargetHandleType'])
54
55         handle = self._conn._handles[target_handle_type, target_handle]
56
57         return (type, requested, handle)
58
59     def channel_exists(self, props):
60         type, _, handle = self._get_type_requested_handle(props)
61
62         if type in self._channels:
63             if handle in self._channels[type]:
64                 return True
65
66         return False
67
68     def channel_for_props(self, props, signal=True, **args):
69         type, _, handle = self._get_type_requested_handle(props)
70
71         if type not in self._requestable_channel_classes:
72             raise NotImplemented('Unknown channel type "%s"' % type)
73
74         if self.channel_exists(props):
75             return self._channels[type][handle]
76
77         channel = self._requestable_channel_classes[type](
78             props, **args)
79
80         self._conn.add_channels([channel], signal=signal)
81         self._channels[type][handle] = channel
82
83         return channel
84
85     def _implement_channel_class(self, type, make_channel, fixed, available):
86         self._requestable_channel_classes[type] = make_channel
87         self._channels.setdefault(type, {})
88
89         self._fixed_properties[type] = fixed
90         self._available_properties[type] = available
91
92     def get_requestable_channel_classes(self):
93         retval = []
94
95         for channel_type in self._requestable_channel_classes:
96             retval.append((self._fixed_properties[channel_type],
97                 self._available_properties[channel_type]))
98
99         return retval