1dafa1ec92914bc43ce4c22dba21e77028eef478
[OpenSRF.git] / src / python / osrf / net_obj.py
1 # -----------------------------------------------------------------------
2 # Copyright (C) 2007  Georgia Public Library Service
3
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 # -----------------------------------------------------------------------
14
15
16 JSON_PAYLOAD_KEY = '__p'
17 JSON_CLASS_KEY = '__c'
18
19 class osrfNetworkObject(object):
20         """Base class for serializable network objects."""
21         def getData(self):
22                 """Returns a dict of data contained by this object"""
23                 return self.data
24
25
26 class __unknown(osrfNetworkObject):
27         """Default class for un-registered network objects."""
28         def __init__(self, data=None):
29                 self.data = data
30
31 setattr(__unknown,'__keys', [])
32 setattr(osrfNetworkObject,'__unknown', __unknown)
33
34
35 def osrfNetworkRegisterHint(hint, keys, type='hash'):
36         """Register a network hint.  
37         
38                 This creates a new class at osrfNetworkObject.<hint> with 
39                 methods for accessing/mutating the object's data.  
40                 Method names will match the names found in the keys array
41
42                 hint - The hint name to encode with the object
43                 type - The data container type.  
44                 keys - An array of data keys.  If type is an 'array', the order of
45                 the keys will determine how the data is accessed
46         """
47
48     #
49     # XXX Surely there is a cleaner way to accomplish this via 
50     # the PythonAPI
51     #
52
53         estr = "class %s(osrfNetworkObject):\n" % hint
54         estr += "\tdef __init__(self, data=None):\n"
55         estr += "\t\tself.data = data\n"
56         estr += "\t\tif data:\n"
57
58         if type == 'hash': 
59                 estr += "\t\t\tpass\n"
60         else:
61                 # we have to make sure the array is large enough        
62                 estr += "\t\t\twhile len(data) < %d:\n" % len(keys)
63                 estr += "\t\t\t\tdata.append(None)\n"
64
65         estr += "\t\telse:\n"
66
67         if type == 'array':
68                 estr += "\t\t\tself.data = []\n"
69                 estr += "\t\t\tfor i in range(%s):\n" % len(keys)
70                 estr += "\t\t\t\tself.data.append(None)\n"
71                 for i in range(len(keys)):
72                         estr += "\tdef %s(self, *args):\n"\
73                                                 "\t\tif len(args) != 0:\n"\
74                                                 "\t\t\tself.data[%s] = args[0]\n"\
75                                                 "\t\treturn self.data[%s]\n" % (keys[i], i, i)
76
77         if type == 'hash':
78                 estr += "\t\t\tself.data = {}\n"
79                 estr += "\t\t\tfor i in %s:\n" % str(keys)
80                 estr += "\t\t\t\tself.data[i] = None\n"
81                 for i in keys:
82                         estr += "\tdef %s(self, *args):\n"\
83                                                 "\t\tif len(args) != 0:\n"\
84                                                 "\t\t\tself.data['%s'] = args[0]\n"\
85                                                 "\t\tval = None\n"\
86                                                 "\t\ttry: val = self.data['%s']\n"\
87                                                 "\t\texcept: return None\n"\
88                                                 "\t\treturn val\n" % (i, i, i)
89
90         estr += "setattr(osrfNetworkObject, '%s', %s)\n" % (hint,hint)
91         estr += "setattr(osrfNetworkObject.%s, '__keys', keys)" % hint
92         exec(estr)
93         
94                 
95
96 # -------------------------------------------------------------------
97 # Define the custom object parsing behavior 
98 # -------------------------------------------------------------------
99 def parseNetObject(obj):
100         hint = None
101         islist = False
102         try:
103                 hint = obj[JSON_CLASS_KEY]
104                 obj = obj[JSON_PAYLOAD_KEY]
105         except: pass
106         if isinstance(obj,list):
107                 islist = True
108                 for i in range(len(obj)):
109                         obj[i] = parseNetObject(obj[i])
110         else: 
111                 if isinstance(obj,dict):
112                         for k,v in obj.iteritems():
113                                 obj[k] = parseNetObject(v)
114
115         if hint: # Now, "bless" the object into an osrfNetworkObject
116                 estr = 'obj = osrfNetworkObject.%s(obj)' % hint
117                 try:
118                         exec(estr)
119                 except AttributeError:
120                         # this object has not been registered, shove it into the default container
121                         obj = osrfNetworkObject.__unknown(obj)
122
123         return obj;
124
125
126
127