diff options
author | Kenneth Anthony Giusti <kgiusti@apache.org> | 2010-03-30 20:09:59 +0000 |
---|---|---|
committer | Kenneth Anthony Giusti <kgiusti@apache.org> | 2010-03-30 20:09:59 +0000 |
commit | feed6024a260189ed210f7a04049a44d2a2e9937 (patch) | |
tree | 8033c7eb7c04e90efb1d0d54e9a5b404695b4e71 | |
parent | 7b39205d3938dcdf87e78d99caa7d69f02212bf8 (diff) | |
download | qpid-python-feed6024a260189ed210f7a04049a44d2a2e9937.tar.gz |
add support for QMF TYPE_LIST in engine, ruby and python wrappers
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@929244 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | qpid/cpp/bindings/qmf/python/qmf.py | 30 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/ruby/qmf.rb | 22 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/agent_ruby.rb | 6 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/tests/python_agent.py | 8 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/python_console.py | 21 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/ruby_console_test.rb | 17 | ||||
-rw-r--r-- | qpid/cpp/src/qmf/engine/ValueImpl.cpp | 167 | ||||
-rw-r--r-- | qpid/cpp/src/qmf/engine/ValueImpl.h | 13 | ||||
-rw-r--r-- | qpid/extras/qmf/src/py/qmf/console.py | 19 |
9 files changed, 254 insertions, 49 deletions
diff --git a/qpid/cpp/bindings/qmf/python/qmf.py b/qpid/cpp/bindings/qmf/python/qmf.py index e4ab581dfd..5dc1330cdb 100644 --- a/qpid/cpp/bindings/qmf/python/qmf.py +++ b/qpid/cpp/bindings/qmf/python/qmf.py @@ -58,10 +58,9 @@ def qmf_to_native(val): elif typecode == TYPE_INT32: return val.asInt() elif typecode == TYPE_INT64: return val.asInt64() elif typecode == TYPE_MAP: return value_to_dict(val) + elif typecode == TYPE_LIST: return value_to_list(val) else: # when TYPE_OBJECT - # when TYPE_LIST - # when TYPE_ARRAY logging.error( "Unsupported type for get_attr? '%s'" % str(val.getType()) ) return None @@ -98,11 +97,9 @@ def native_to_qmf(target, value): elif typecode == TYPE_INT32: val.setInt(value) elif typecode == TYPE_INT64: val.setInt64(value) elif typecode == TYPE_MAP: dict_to_value(val, value) + elif typecode == TYPE_LIST: list_to_value(val, value) else: - # when TYPE_MAP # when TYPE_OBJECT - # when TYPE_LIST - # when TYPE_ARRAY logging.error("Unsupported type for get_attr? '%s'" % str(val.getType())) return None return val @@ -129,6 +126,7 @@ def pick_qmf_type(value): if value.__class__ == bool: return TYPE_BOOL if value == None: return TYPE_BOOL if value.__class__ == dict: return TYPE_MAP + if value.__class__ == list: return TYPE_LIST raise "QMF type not known for native type %s" % value.__class__ @@ -140,7 +138,7 @@ def value_to_dict(val): key = val.key(i) mymap[key] = qmf_to_native(val.byKey(key)) return mymap - + def dict_to_value(val, mymap): for key, value in mymap.items(): @@ -149,6 +147,26 @@ def dict_to_value(val, mymap): val.insert(key, native_to_qmf(typecode, value)) +def value_to_list(val): + mylist = [] + if val.isList(): + for i in range(val.listItemCount()): + mylist.append(qmf_to_native(val.listItem(i))) + return mylist + #if val.isArray(): + # for i in range(val.arrayItemCount()): + # mylist.append(qmf_to_native(val.arrayItem(i))) + # return mylist + + raise "value_to_list must be given a list value" + + +def list_to_value(val, mylist): + for item in mylist: + typecode = pick_qmf_type(item) + val.appendToList(native_to_qmf(typecode, item)) + + ##============================================================================== ## CONNECTION ##============================================================================== diff --git a/qpid/cpp/bindings/qmf/ruby/qmf.rb b/qpid/cpp/bindings/qmf/ruby/qmf.rb index ce824b3605..823cf9bf93 100644 --- a/qpid/cpp/bindings/qmf/ruby/qmf.rb +++ b/qpid/cpp/bindings/qmf/ruby/qmf.rb @@ -48,8 +48,8 @@ module Qmf when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt when TYPE_INT64 then val.asInt64 when TYPE_MAP then value_to_dict(val) + when TYPE_LIST then value_to_list(val) when TYPE_OBJECT - when TYPE_LIST when TYPE_ARRAY end end @@ -77,8 +77,8 @@ module Qmf when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(value) when TYPE_INT64 then val.setInt64(value) when TYPE_MAP then dict_to_value(val, value) + when TYPE_LIST then list_to_value(val, value) when TYPE_OBJECT - when TYPE_LIST when TYPE_ARRAY end return val @@ -112,6 +112,7 @@ module Qmf return TYPE_BOOL if value.class == NilClass return TYPE_MAP if value.class == Hash + return TYPE_LIST if value.class == Array raise ArgumentError, "QMF type not known for native type #{value.class}" end @@ -134,6 +135,23 @@ module Qmf val.insert(key, native_to_qmf(typecode, value)) end end + + def value_to_list(val) + # Assume val is of type Qmfengine::Value + raise ArgumentError, "value_to_dict must be given a map value" if !val.isList + list = [] + for i in 0...val.listItemCount + list.push(qmf_to_native(val.listItem(i))) + end + return list + end + + def list_to_value(val, list) + list.each do |value| + typecode = pick_qmf_type(value) + val.appendToList(native_to_qmf(typecode, value)) + end + end end $util = Util.new diff --git a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb index 86eefc59a6..92065031a2 100755 --- a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb +++ b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb @@ -44,6 +44,7 @@ class Model @parent_class.add_property(Qmf::SchemaProperty.new("lstrval", Qmf::TYPE_LSTR)) @parent_class.add_property(Qmf::SchemaProperty.new("mapval", Qmf::TYPE_MAP)) + @parent_class.add_property(Qmf::SchemaProperty.new("listval", Qmf::TYPE_LIST)) @parent_class.add_statistic(Qmf::SchemaStatistic.new("queryCount", Qmf::TYPE_UINT32, :unit => "query", :desc => "Query count")) @@ -246,6 +247,11 @@ class App < Qmf::AgentHandler @parent.int16val = 0 @parent.int8val = 0 + # a list containing a list that contains a map (so there!) + @parent.listval = ['a', 1, 'b', 2, + ['c', true, 3.1415, + {"hi" => 10, "lo" => 5}]] + @parent_oid = @agent.alloc_object_id(1) @parent.set_object_id(@parent_oid) diff --git a/qpid/cpp/bindings/qmf/tests/python_agent.py b/qpid/cpp/bindings/qmf/tests/python_agent.py index 83531830b1..4974e0ec90 100644 --- a/qpid/cpp/bindings/qmf/tests/python_agent.py +++ b/qpid/cpp/bindings/qmf/tests/python_agent.py @@ -45,6 +45,7 @@ class Model: self.parent_class.add_property(qmf.SchemaProperty("lstrval", qmf.TYPE_LSTR)) self.parent_class.add_property(qmf.SchemaProperty("mapval", qmf.TYPE_MAP)) + self.parent_class.add_property(qmf.SchemaProperty("listval", qmf.TYPE_LIST)) self.parent_class.add_statistic(qmf.SchemaStatistic("queryCount", qmf.TYPE_UINT32, {"unit":"query", "desc":"Query count"})) @@ -274,7 +275,7 @@ class App(qmf.AgentHandler): ## @todo how do we force a test failure? # verify the properties() and statistics() object methods: - assert len(self._parent.properties()) == 13 + assert len(self._parent.properties()) == 14 assert len(self._parent.statistics()) == 1 self._parent.set_attr("name", "Parent One") @@ -290,6 +291,11 @@ class App(qmf.AgentHandler): self._parent.set_attr("int16val", 0) self._parent.set_attr("int8val", 0) + # a list containing a list that contains a map (so there!) + self._parent.set_attr("listval", ['a', 1, 'b', 2, + ['c', True, 3.1415, + {"hi": 10, "lo": 5}]]) + self._parent_oid = self._agent.alloc_object_id(1) self._parent.set_object_id(self._parent_oid) diff --git a/qpid/cpp/bindings/qmf/tests/python_console.py b/qpid/cpp/bindings/qmf/tests/python_console.py index fe27c33c4b..efd25a1d26 100755 --- a/qpid/cpp/bindings/qmf/tests/python_console.py +++ b/qpid/cpp/bindings/qmf/tests/python_console.py @@ -202,7 +202,26 @@ class QmfInteropTests(TestBase010): self.assertEqual(queue[3].arguments["strval"], "TEST") self.assertEqual(queue[4].arguments["uint32val"], 0) self.assertEqual(queue[4].arguments["strval"], "LONG_TEST") - + + + def test_G_basic_map_list_data(self): + self.startQmf(); + qmf = self.qmf + + parents = qmf.getObjects(_class="parent") + self.assertEqual(len(parents), 1) + parent = parents[0] + + # see agent for structure of listval + + self.assertTrue(isinstance(parent.listval, list)) + self.assertEqual(len(parent.listval), 5) + self.assertTrue(isinstance(parent.listval[4], list)) + self.assertEqual(len(parent.listval[4]), 4) + self.assertTrue(isinstance(parent.listval[4][3], dict)) + self.assertEqual(parent.listval[4][3]["hi"], 10) + self.assertEqual(parent.listval[4][3]["lo"], 5) + def getProperty(self, msg, name): for h in msg.headers: diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb index 3a771aaafd..9ef0ef57a8 100755 --- a/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb +++ b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb @@ -266,6 +266,23 @@ class ConsoleTest < ConsoleTestBase end end + + + def test_G_basic_map_list_data + parent = @qmfc.object(:class => "parent") + assert(parent, "Number of 'parent' objects") + + # see agent for structure of listval + + assert(parent.listval.class == Array) + assert_equal(parent.listval.length, 5) + assert(parent.listval[4].class == Array) + assert_equal(parent.listval[4].length, 4) + assert(parent.listval[4][3].class == Hash) + assert_equal(parent.listval[4][3]["hi"], 10) + assert_equal(parent.listval[4][3]["lo"], 5) + end + end app = ConsoleTest.new diff --git a/qpid/cpp/src/qmf/engine/ValueImpl.cpp b/qpid/cpp/src/qmf/engine/ValueImpl.cpp index b1c027520f..72c68c420b 100644 --- a/qpid/cpp/src/qmf/engine/ValueImpl.cpp +++ b/qpid/cpp/src/qmf/engine/ValueImpl.cpp @@ -18,20 +18,23 @@ */ #include "qmf/engine/ValueImpl.h" -#include <qpid/framing/FieldTable.h> #include <qpid/framing/FieldValue.h> +#include <qpid/framing/FieldTable.h> +#include <qpid/framing/List.h> using namespace std; using namespace qmf::engine; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::framing::FieldValue; +//using qpid::framing::Buffer; +//using qpid::framing::FieldTable; +//using qpid::framing::FieldValue; +using namespace qpid::framing; ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t) { uint64_t first; uint64_t second; FieldTable ft; + List fl; switch (typecode) { case TYPE_UINT8 : value.u32 = (uint32_t) buf.getOctet(); break; @@ -62,6 +65,10 @@ ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t) break; case TYPE_LIST: + fl.decode(buf); + initList(fl); + break; + case TYPE_ARRAY: case TYPE_OBJECT: default: @@ -126,7 +133,7 @@ void ValueImpl::initMap(const FieldTable& ft) Value* subval(new Value(TYPE_DOUBLE)); subval->setDouble(fvalue.get<double>()); insert(name.c_str(), subval); - } else { + } else if (amqType == 0xa8) { FieldTable subFt; bool valid = qpid::framing::getEncodedValue<FieldTable>(iter->second, subFt); if (valid) { @@ -134,6 +141,14 @@ void ValueImpl::initMap(const FieldTable& ft) subval->impl->initMap(subFt); insert(name.c_str(), subval); } + } else if (amqType == 0xa9) { + List subList; + bool valid = qpid::framing::getEncodedValue<List>(iter->second, subList); + if (valid) { + Value* subval(new Value(TYPE_LIST)); + subval->impl->initList(subList); + insert(name.c_str(), subval); + } } } } @@ -185,6 +200,14 @@ void ValueImpl::mapToFieldTable(FieldTable& ft) const ft.setTable(name, subFt); break; case TYPE_LIST: + { + List subList; + subval.impl->listToFramingList(subList); + ft.set(name, + ::qpid::framing::FieldTable::ValuePtr( + new ListValue( + subList))); + } break; case TYPE_ARRAY: case TYPE_OBJECT: case TYPE_UUID: @@ -195,9 +218,126 @@ void ValueImpl::mapToFieldTable(FieldTable& ft) const } } + +void ValueImpl::initList(const List& fl) +{ + for (List::const_iterator iter = fl.begin(); + iter != fl.end(); iter++) { + const FieldValue& fvalue(*iter->get()); + uint8_t amqType = fvalue.getType(); + + if (amqType == 0x32) { + Value* subval(new Value(TYPE_UINT64)); + subval->setUint64(fvalue.get<int64_t>()); + appendToList(subval); + } else if ((amqType & 0xCF) == 0x02) { + Value* subval(new Value(TYPE_UINT32)); + switch (amqType) { + case 0x02 : subval->setUint(fvalue.get<int>()); break; + case 0x12 : subval->setUint(fvalue.get<int>()); break; + case 0x22 : subval->setUint(fvalue.get<int>()); break; + } + appendToList(subval); + } else if ((amqType & 0xCF) == 0x01) { + Value* subval(new Value(TYPE_INT64)); + subval->setInt64(fvalue.get<int64_t>()); + appendToList(subval); + } else if (amqType == 0x85 || amqType == 0x95) { + Value* subval(new Value(TYPE_LSTR)); + subval->setString(fvalue.get<string>().c_str()); + appendToList(subval); + } else if (amqType == 0x23 || amqType == 0x33) { + Value* subval(new Value(TYPE_DOUBLE)); + subval->setDouble(fvalue.get<double>()); + appendToList(subval); + } else if (amqType == 0xa8) { + FieldTable subFt; + bool valid = qpid::framing::getEncodedValue<FieldTable>(*iter, subFt); + if (valid) { + Value* subval(new Value(TYPE_MAP)); + subval->impl->initMap(subFt); + appendToList(subval); + } + } else if (amqType == 0xa9) { + List subList; + bool valid = qpid::framing::getEncodedValue<List>(*iter, subList); + if (valid) { + Value *subVal(new Value(TYPE_LIST)); + subVal->impl->initList(subList); + appendToList(subVal); + } + } + } +} + +void ValueImpl::listToFramingList(List& fl) const +{ + for (vector<Value>::const_iterator iter = vectorVal.begin(); + iter != vectorVal.end(); iter++) { + const Value& subval(*iter); + + switch (subval.getType()) { + case TYPE_UINT8: + case TYPE_UINT16: + case TYPE_UINT32: + fl.push_back(List::ValuePtr(new Unsigned64Value((uint64_t) subval.asUint()))); + break; + case TYPE_UINT64: + case TYPE_DELTATIME: + fl.push_back(List::ValuePtr(new Unsigned64Value(subval.asUint64()))); + break; + case TYPE_SSTR: + case TYPE_LSTR: + fl.push_back(List::ValuePtr(new Str16Value(subval.asString()))); + break; + case TYPE_INT64: + case TYPE_ABSTIME: + fl.push_back(List::ValuePtr(new Integer64Value(subval.asInt64()))); + break; + case TYPE_BOOL: + fl.push_back(List::ValuePtr(new IntegerValue(subval.asBool() ? 1 : 0))); + break; + case TYPE_FLOAT: + fl.push_back(List::ValuePtr(new FloatValue(subval.asFloat()))); + break; + case TYPE_DOUBLE: + fl.push_back(List::ValuePtr(new DoubleValue(subval.asDouble()))); + break; + case TYPE_INT8: + case TYPE_INT16: + case TYPE_INT32: + fl.push_back(List::ValuePtr(new IntegerValue(subval.asInt()))); + break; + case TYPE_MAP: + { + FieldTable subFt; + subval.impl->mapToFieldTable(subFt); + fl.push_back(List::ValuePtr(new FieldTableValue(subFt))); + + } break; + case TYPE_LIST: + { + List subList; + subval.impl->listToFramingList(subList); + fl.push_back(List::ValuePtr(new ListValue(subList))); + } break; + + case TYPE_ARRAY: + case TYPE_OBJECT: + case TYPE_UUID: + case TYPE_REF: + default: + break; + } + } + } + + + void ValueImpl::encode(Buffer& buf) const { FieldTable ft; + List fl; switch (typecode) { case TYPE_UINT8 : buf.putOctet((uint8_t) value.u32); break; @@ -222,6 +362,10 @@ void ValueImpl::encode(Buffer& buf) const ft.encode(buf); break; case TYPE_LIST: + listToFramingList(fl); + fl.encode(buf); + break; + case TYPE_ARRAY: case TYPE_OBJECT: default: @@ -280,19 +424,6 @@ const char* ValueImpl::key(uint32_t idx) const return iter->first.c_str(); } -Value* ValueImpl::listItem(uint32_t) -{ - return 0; -} - -void ValueImpl::appendToList(Value*) -{ -} - -void ValueImpl::deleteListItem(uint32_t) -{ -} - Value* ValueImpl::arrayItem(uint32_t) { return 0; diff --git a/qpid/cpp/src/qmf/engine/ValueImpl.h b/qpid/cpp/src/qmf/engine/ValueImpl.h index 84b0e768e6..3b535834fd 100644 --- a/qpid/cpp/src/qmf/engine/ValueImpl.h +++ b/qpid/cpp/src/qmf/engine/ValueImpl.h @@ -33,6 +33,7 @@ namespace qpid { namespace framing { class FieldTable; + class List; } } @@ -138,13 +139,14 @@ namespace engine { bool isList() const { return typecode == TYPE_LIST; } uint32_t listItemCount() const { return vectorVal.size(); } - Value* listItem(uint32_t idx); - void appendToList(Value* val); - void deleteListItem(uint32_t idx); + Value* listItem(uint32_t idx) { return idx < listItemCount() ? &vectorVal[idx] : 0; } + const Value* listItem(uint32_t idx) const { return idx < listItemCount() ? &vectorVal[idx] : 0; } + void appendToList(Value* val) { vectorVal.push_back(*val); } + void deleteListItem(uint32_t idx) { if (idx < listItemCount()) vectorVal.erase(vectorVal.begin()+idx); } bool isArray() const { return typecode == TYPE_ARRAY; } Typecode arrayType() const { return arrayTypecode; } - uint32_t arrayItemCount() const { return vectorVal.size(); } + uint32_t arrayItemCount() const { return 0; } Value* arrayItem(uint32_t idx); void appendToArray(Value* val); void deleteArrayItem(uint32_t idx); @@ -152,6 +154,9 @@ namespace engine { private: void mapToFieldTable(qpid::framing::FieldTable& ft) const; void initMap(const qpid::framing::FieldTable& ft); + + void listToFramingList(qpid::framing::List& fl) const; + void initList(const qpid::framing::List& fl); }; } } diff --git a/qpid/extras/qmf/src/py/qmf/console.py b/qpid/extras/qmf/src/py/qmf/console.py index b663116f40..7bda233b9a 100644 --- a/qpid/extras/qmf/src/py/qmf/console.py +++ b/qpid/extras/qmf/src/py/qmf/console.py @@ -985,15 +985,7 @@ class Session: data = Object(self, broker, schema, codec, True, True, False) else: data = self._decodeValue(codec, inner_type_code, broker) - elif typecode == 21: # List - #taken from codec10.read_list - sc = Codec(codec.read_vbin32()) - count = sc.read_uint32() - data = [] - while count > 0: - type = sc.read_uint8() - data.append(self._decodeValue(sc,type,broker)) - count -= 1 + elif typecode == 21: data = codec.read_list() # List elif typecode == 22: #Array #taken from codec10.read_array sc = Codec(codec.read_vbin32()) @@ -1028,14 +1020,7 @@ class Session: elif typecode == 19: codec.write_int64 (int(value)) # S64 elif typecode == 20: value._encodeUnmanaged(codec) # OBJECT elif typecode == 15: codec.write_map (value) # FTABLE - elif typecode == 21: # List - sc = Codec() - self._encodeValue(sc, len(value), 3) - for o in value: - ltype=self.encoding(o) - self._encodeValue(sc,ltype,1) - self._encodeValue(sc, o, ltype) - codec.write_vbin32(sc.encoded) + elif typecode == 21: codec.write_list (value) # List elif typecode == 22: # Array sc = Codec() self._encodeValue(sc, len(value), 3) |