Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 1 | # -*- coding: utf-8 -*-
|
| 2 | """ 一卡通后台通讯协议包封装
|
| 3 | 所有数据都是 unicode utf-8 编码
|
| 4 | """
|
| 5 | import traceback
|
| 6 | import simplejson as json
|
| 7 |
|
| 8 |
|
| 9 | def _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 |
|
| 18 | class 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 |
|
| 89 | class 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
|
Tang Cheng | bee49e4 | 2012-11-19 10:56:07 +0800 | [diff] [blame^] | 156 | if (self._row_no + 1) < len(self._row_data):
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 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 Cheng | 3e7feba | 2012-11-09 16:51:27 +0800 | [diff] [blame] | 174 | if arg is None:
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 175 | 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
|