00001 import roslib; roslib.load_manifest("cassandra_ros")
00002 import rospy
00003 import std_msgs.msg
00004 import rosmsg
00005 import genpy
00006
00007 import pickle
00008 import pycassa
00009
00010 from CassandraTopic_ import *
00011
00012 class CassandraTopic_ros(CassandraTopic_):
00013 def __init__(self, MsgClass):
00014 CassandraTopic_.__init__(MsgClass)
00015
00016 def getColumnValidationClasses(self):
00017 msg = self.MsgClass()
00018
00019 spec = rosmsg.get_msg_text(msg._type)
00020 spec = spec.split('\n')
00021 spec.remove("")
00022 spec, _ = self._parseMsg(spec)
00023
00024 spec = self._translateSpecToCassandra(spec)
00025
00026
00027
00028 return spec
00029
00030 def _translateSpecToCassandra(self, spec):
00031 for key in spec.keys():
00032 if spec[key] in ('int8', 'int16', 'int32', 'uint8','uint16', 'uint32'):
00033 spec[key] = pycassa.INT_TYPE
00034 elif spec[key] in ('int64', 'uint64'):
00035 spec[key] = pycassa.LONG_TYPE
00036 elif spec[key] in ('float32'):
00037 spec[key] = pycassa.FLOAT_TYPE
00038 elif spec[key] in ('float64'):
00039 spec[key] = pycassa.DOUBLE_TYPE
00040 elif spec[key] in ('char', 'string', 'char[]'):
00041 spec[key] = pycassa.UTF8_TYPE
00042 elif spec[key] in ('time', 'duration'):
00043 spec[key] = pycassa.DATE_TYPE
00044 elif spec[key] in ('bool'):
00045 spec[key] = pycassa.BOOLEAN_TYPE
00046 else:
00047 spec[key] = pycassa.BYTES_TYPE
00048 return spec
00049
00050 def _parseMsg(self, defs, parent=""):
00051 _dict = {}
00052 parent += "."
00053 i = 0
00054 while i< len(defs):
00055
00056 _type, _name = defs[i].replace(' ','').split(" ")
00057
00058
00059 if len(defs)-1 == i:
00060 _dict[parent+_name] = _type
00061 elif defs[i].count(" ") == defs[i+1].count(" "):
00062 _dict[parent+_name] = _type
00063 elif defs[i].count(" ") > defs[i+1].count(" "):
00064 _dict[parent+_name] = _type
00065 break
00066 else:
00067
00068 if _type.endswith("[]"):
00069 _name += "[]"
00070 _d, _i = self._parseMsg(defs[i+1:], parent+_name)
00071
00072 i += _i+1
00073 for key in _d.keys():
00074 _dict[key] = _d[key]
00075
00076 i += 1
00077
00078 return _dict, i
00079
00080 def encode(self, msg):
00081 return self._ros_to_cassandra(msg)
00082
00083 def decode(self, data):
00084 msg = self.MsgClass()
00085 _dict = self._cassandra_to_dict(data)
00086 msg = self._dict_to_ros(_dict, msg)
00087 return msg
00088
00089 def _value_to_cassandra(self ,data, parent):
00090
00091 if type(data) in ( str, int, float, long, bool ):
00092 return { parent : data }
00093 elif isinstance(data, (genpy.rostime.Time, genpy.rostime.Duration)):
00094 return { parent : data.to_time() }
00095 elif type(data) in (list, tuple):
00096 if len(data) == 0:
00097 return { parent: pickle.dumps(data) }
00098 elif type(data[0]) in ( str, int, float, long, bool ):
00099 return { parent: pickle.dumps(data) }
00100 else:
00101 _dict = {}
00102 for i in range(len(data)):
00103 res = self._value_to_cassandra(data[i], parent)
00104 for key in res.keys():
00105 _dict[key] = res[key]
00106 return _dict
00107 elif isinstance(data, rospy.Message):
00108 return self._ros_to_cassandra(data, parent)
00109 else:
00110 raise CassandraTopicException("unknown type: %s"%type(data))
00111
00112
00113 def _ros_to_cassandra(self, data, parent=""):
00114 if not isinstance(data, rospy.Message):
00115
00116 return self._value_to_cassandra(data, parent)
00117
00118 _dict = {}
00119
00120 parent += "."
00121
00122 for elem in data.__slots__:
00123 sub_elements = self._value_to_cassandra( getattr(data, elem) , parent+elem)
00124
00125 if type(sub_elements) == dict:
00126 for key in sub_elements.keys():
00127 _dict[key] = sub_elements[key]
00128
00129 return _dict
00130
00131
00132
00133 def _value_to_dict(self, name, value, _dict):
00134
00135
00136 if name[0][-1] == ']':
00137 ar = name[0].find('[')
00138 element = int(name[0][ar+1:-1])
00139 name[0] = name[0][:ar]
00140
00141
00142 if _dict.has_key(name[0]):
00143 if len(_dict[name[0]]) == element:
00144 _dict[name[0]].append(self._value_to_dict(name[1:], value, {}))
00145 else:
00146 _dict[name[0]][element] = self._value_to_dict(name[1:], value, _dict[name[0]][element])
00147 else:
00148 _dict[name[0]] = [self._value_to_dict(name[1:], value, {})]
00149
00150 elif len(name) == 1:
00151 _dict[name[0]] = value
00152
00153 else:
00154 if not _dict.has_key(name[0]):
00155 _dict[name[0]] = self._value_to_dict(name[1:], value, {})
00156 else:
00157 _dict[name[0]] = self._value_to_dict(name[1:], value, _dict[name[0]])
00158
00159 return _dict
00160
00161 def _cassandra_to_dict(self, data):
00162 _dict = {}
00163
00164 for key in data.keys():
00165 name = key.split(".")
00166 _dict = self._value_to_dict(name[1:], data[key], _dict)
00167 return _dict
00168
00169 def _dict_to_value(self, _dict, _slot, _type):
00170
00171 if isinstance(_slot, (str, int, float, bool)):
00172 return _dict
00173 elif isinstance(_slot, (list, dict, tuple)):
00174 msg = []
00175
00176 if _type in ('bool[]', 'int8[]', 'uint8[]', 'int16[]', 'uint16[]', 'int32[]', 'uint32[]',
00177 'int64[]', 'uint64[]', 'float32[]', 'float64[]', 'string[]'):
00178 msg = pickle.loads(_dict)
00179 else:
00180 _type = _type.replace("[]","")
00181 _slot = genpy.message.get_message_class(_type)()
00182 for elem in _dict:
00183 msg.append( self._dict_to_ros( elem, _slot) )
00184 return msg
00185 elif isinstance(_slot, (genpy.rostime.Time, genpy.rostime.Duration)):
00186 t = rospy.Time()
00187 t.set(int(_dict.strftime('%s')), _dict.microsecond)
00188 return t
00189 elif isinstance(_slot, rospy.Message):
00190 return self._dict_to_ros(_dict, _slot)
00191 else:
00192 raise RosCassandraTranspileException("unknown type: %s"%type(_slot))
00193
00194 def _dict_to_ros(self, _dict, msg):
00195
00196 for i in range(len(msg.__slots__)):
00197 _slot = msg.__slots__[i]
00198 _type = msg._slot_types[i]
00199
00200 setattr(msg,
00201 _slot,
00202 self._dict_to_value( _dict[_slot],
00203 getattr(msg, _slot),
00204 _type))
00205
00206 return msg