1
2
3
4
5 """ Builder module for services.
6 """
7
8 from xml.etree import cElementTree as ElementTree
9
10 from brisa.core import log
11
12 from brisa.upnp.base_action import BaseArgument, BaseAction
13 from brisa.upnp.base_service import BaseStateVariable
14
15
17
19 self.service = service
20 self.fd = fd
21 self._actions = {}
22 self._variables = {}
23
25 """ Builds a service given a file descriptor containing the SCPD XML.
26
27 @return: True if service build succeeded, otherwise False.
28 @rtype: bool
29 """
30 if not self._parse_description(self.fd):
31 return False
32 self._build_service()
33 return True
34
36 """ Parses the actions and state variables of a service given a file
37 descriptor containing the SCPD XML. File descriptor must be open.
38
39 @param fd: file descriptor
40 @type fd: file
41
42 @return: True if service parser succeeded, otherwise False.
43 @rtype: bool
44 """
45 try:
46 data = fd.read()
47 data = data[data.find("<"):data.rfind(">")+1]
48 tree = ElementTree.XML(data)
49 if tree:
50 self._parse_actions(tree)
51 self._parse_variables(tree)
52 return True
53 except Exception, e:
54 log.debug('Could not build service SCPD XML. %s' % str(e))
55
56 return False
57
59 """ Parses actions from a fetched tree.
60
61 @param tree: tree containing the actions
62 @type tree: ElementTree
63 """
64 ns = "urn:schemas-upnp-org:service-1-0"
65 for node in tree.findall('.//{%s}action' % ns):
66 name = node.findtext('{%s}name' % ns)
67 args = []
68 for arg in node.findall('.//{%s}argument' % ns):
69 arg_direction = arg.findtext('{%s}direction' % ns)
70 arg_state_var = arg.findtext('{%s}relatedStateVariable' % ns)
71 arg_name = arg.findtext('{%s}name' % ns)
72 args.append((arg_name, arg_direction, arg_state_var))
73 self._actions[name] = args
74
76 """ Parses variables from a fetched tree.
77
78 @param tree: tree containing the actions
79 @type tree: ElementTree
80 """
81 ns = "urn:schemas-upnp-org:service-1-0"
82 for node in tree.findall('.//{%s}stateVariable' % ns):
83
84 send_events = node.attrib.get('sendEvents', 'no')
85
86 multicast = node.attrib.get('multicast', 'no')
87
88 name = node.findtext('{%s}name' % ns)
89 data_type = node.findtext('{%s}dataType' % ns)
90 values = [a.text for a in node.findall('.//{%s}allowedValue' % ns)]
91 self._variables[name] = (send_events, multicast, data_type, values)
92
94 """ Builds a service.
95 """
96 for name in self._variables.iterkeys():
97 send_events, multicast, data_type, values = self._variables[name]
98 send_events = True if send_events == 'yes' else False
99 multicast = True if multicast == 'yes' else False
100 self.service.add_state_variable(self.\
101 _create_state_var(name, send_events,
102 multicast, data_type, values))
103 for action_name, action_args in self._actions.iteritems():
104 args = []
105 for arg_name, arg_direction, arg_state_var in action_args:
106 args.append(self._create_argument(arg_name,
107 arg_direction,
108 self.service._state_variables[arg_state_var]))
109 self.service._actions[action_name] = self.\
110 _create_action(action_name, args)
111
113 """ Factory method that creates an action argument.
114
115 @return: The argument object.
116 @rtype: BaseArgument
117 """
118 return BaseArgument(arg_name, arg_direction, arg_state_var)
119
121 """ Factory method that creates a service action.
122
123 @return: The action object.
124 @rtype: BaseAction
125 """
126 return BaseAction(self.service, name, args)
127
130 """ Factory method that creates a service state variable.
131
132 @return: The state variable object.
133 @rtype: BaseStateVariable
134 """
135 return BaseStateVariable(self.service,
136 name, send_events, multicast, data_type, values)
137