blob: 6ecac960d4ee08f3d948a07ecd86ff900b228ab3 [file] [log] [blame]
Tang Cheng53ca4872012-11-05 14:00:43 +08001# -*- coding: utf-8 -*-
2""" 一卡通后台通讯协议包封装
3所有数据都是 unicode utf-8 编码
4"""
5import traceback
6import simplejson as json
7
8
9def _unicode_str(value):
10 if isinstance(value, str):
11 return value.decode('utf-8')
12 elif isinstance(value, unicode):
13 return value
14 else:
15 return unicode(value)
16
17
18class message_writer:
19 """ 后台消息写接口
20 """
21 def __init__(self):
22 self.clear()
23
24 def clear(self):
25 self._attr = {}
26 self._row_data = []
27 self._col_names = []
28 self._row = {}
29 self._frozen = False
30
31 def attr(self, name, value):
32 if name in self._attr:
33 raise ValueError('Attribute [%s] already exists' % name)
34 self._attr[name] = _unicode_str(value)
35 return self
36
37 def row(self, name, value):
38 if not (name in self._col_names):
39 self._col_names.append(name)
40 self._row[name] = _unicode_str(value)
41
42 def add_row(self):
43 if not self._row:
44 raise ValueError('Row has no values')
45 self._row_data.append(self._row)
46 self._row = {}
47 return len(self._row_data)
48
49 def append_row(self, row):
50 if not self._col_names:
51 for k, v in row.iteritems():
52 self._col_names.append(k)
53 self._row_data.append(row)
54 else:
55 new_row = dict([(v, row.get(v, None)) for v in self._col_names])
56 self._row_data.append(new_row)
57
58 def _normalize(self):
59 colcnt = len(self._col_names)
60 rowcnt = len(self._row_data)
61 self._attr["colcnt"] = colcnt
62 self._attr["rowcnt"] = rowcnt
63 if colcnt > 0:
64 self._attr["colname"] = self._col_names
65 self._attr["coldesc"] = self._col_names
66
67 if rowcnt > 0 and colcnt <= 0:
68 raise ValueError(u'数据没有列值')
69
70 if rowcnt > 0:
71 self._attr["rowdata"] = [[row.get(colname, u"") for colname in self._col_names]
72 for row in self._row_data]
73 self._frozen = True
74
75 def serialize(self):
76 """ 返回 unicode utf-8编码
77 """
78 if not self._frozen:
79 self._normalize()
80 seri = json.dumps(self._attr, ensure_ascii=False, encoding='utf-8')
81 return seri
82
83 def root(self):
84 if not self._frozen:
85 self._normalize()
86 return self._attr
87
88
89class message_reader:
90 """ 后台消息读接口
91 """
92 def __init__(self):
93 self.clear()
94
95 def clear(self):
96 """ 清空数据
97 """
98 self._attr = {}
99 self._row_data = None
100 self._col_names = []
101 self._col_desc = []
102 self._row_no = -1
103 self._frozen = False
104
105 def unserialize(self, message):
106 """ 解析报文
107 """
108 self.clear()
109 try:
110 message = _unicode_str(message)
111 obj = json.loads(message)
112 #obj = json.loads(msg.replace('\\',"\\\\"))
113 except Exception, ex:
114 traceback.print_exc()
115 raise ValueError(u'解析报文错误,' + ex.message)
116
117 if u"colname" in obj:
118 colname = obj[u"colname"]
119 colcnt = obj[u"colcnt"]
120 rowcnt = obj[u"rowcnt"]
121
122 if colcnt != len(colname):
123 raise ValueError(u'记录列数定义不符')
124
125 rowdata = obj[u"rowdata"]
126 if rowcnt != len(rowdata):
127 raise ValueError(u'记录行数定义不符')
128
129 self._row_data = [dict(zip(colname, row)) for row in rowdata]
130 self._col_names = colname
131 self._col_desc = obj["coldesc"]
132 else:
133 pass
134
135 for n, v in obj.iteritems():
136 if n in (u"colname", u"colcnt", u"rowcnt", u"coldesc", u"rowdata"):
137 continue
138 self._attr[n] = v
139 self._frozen = True
140 #print self._attr
141
142 def attr(self, name):
143 """ 获取属性值,如果没有改属性返回空字符串
144 """
145 assert self._frozen == True
146 if name not in self._attr:
147 return ""
148 return self._attr[name]
149
150 def has_more_row(self):
151 """ 判断是否有后续行
152 """
153 assert self._frozen == True
154 if not self._row_data:
155 return False
156 if self._row_no < len(self._row_data):
157 return True
158 return False
159
160 def next_row(self):
161 """ 将读取指针移到下一行
162 """
163 assert self._frozen == True
164 assert self.has_more_row()
165 self._row_no += 1
166
167 _ARG_DEFAULT = []
168
169 def col(self, name, default=[], strip=True):
170 """ 获取当前行的字段值
171 """
172 assert self._row_no >= 0
173 arg = self._row_data[self._row_no].get(name, None)
Tang Cheng3e7feba2012-11-09 16:51:27 +0800174 if arg is None:
Tang Cheng53ca4872012-11-05 14:00:43 +0800175 if strip and default == message_reader._ARG_DEFAULT:
176 raise IndexError(u'no such column %s' % name)
177 return default
178 return arg
179
180 def is_eof(self):
181 """判断是否到记录尾
182 """
183 if self._row_no >= len(self._row_data):
184 return True
185 return False
186
187 def fetch_rows(self):
188 """ 读取所有行记录
189 """
190 if not self.has_more_row():
191 return
192 self._row_no = 0
193 for row in self._row_data:
194 self._row_no += 1
195 yield row