summaryrefslogtreecommitdiff
path: root/qpid/cpp
diff options
context:
space:
mode:
authorTed Ross <tross@apache.org>2010-01-05 19:45:28 +0000
committerTed Ross <tross@apache.org>2010-01-05 19:45:28 +0000
commit25d63a161d11d504e51ead2f76e761f561503b69 (patch)
tree8f018d410a0d9ba554afc61f0f603407ffd1ecb6 /qpid/cpp
parentf41fee09de1f40adc1323e7d811a5a76bc0b6edc (diff)
downloadqpid-python-25d63a161d11d504e51ead2f76e761f561503b69.tar.gz
Added handling of MAP values for the wrapped QMF interfaces.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@896191 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp')
-rw-r--r--qpid/cpp/bindings/qmf/python/qmf.py234
-rw-r--r--qpid/cpp/bindings/qmf/ruby/qmf.rb188
-rw-r--r--qpid/cpp/bindings/qmf/ruby/ruby.i2
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/agent_ruby.rb27
-rw-r--r--qpid/cpp/bindings/qmf/tests/python_agent.py46
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/ruby_console_test.rb38
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/run_interop_tests12
-rw-r--r--qpid/cpp/include/qpid/framing/FieldValue.h2
-rw-r--r--qpid/cpp/src/qmf/engine/ValueImpl.cpp120
-rw-r--r--qpid/cpp/src/qmf/engine/ValueImpl.h10
-rw-r--r--qpid/cpp/src/qpid/framing/FieldValue.cpp2
11 files changed, 477 insertions, 204 deletions
diff --git a/qpid/cpp/bindings/qmf/python/qmf.py b/qpid/cpp/bindings/qmf/python/qmf.py
index 233f1c83d8..c00c777878 100644
--- a/qpid/cpp/bindings/qmf/python/qmf.py
+++ b/qpid/cpp/bindings/qmf/python/qmf.py
@@ -35,6 +35,118 @@ from qmfengine import (TYPE_ABSTIME, TYPE_ARRAY, TYPE_BOOL, TYPE_DELTATIME,
from qmfengine import (O_EQ, O_NE, O_LT, O_LE, O_GT, O_GE, O_RE_MATCH, O_RE_NOMATCH,
E_NOT, E_AND, E_OR, E_XOR)
+
+def qmf_to_native(val):
+ typecode = val.getType()
+ if typecode == TYPE_UINT8: return val.asUint()
+ elif typecode == TYPE_UINT16: return val.asUint()
+ elif typecode == TYPE_UINT32: return val.asUint()
+ elif typecode == TYPE_UINT64: return val.asUint64()
+ elif typecode == TYPE_SSTR: return val.asString()
+ elif typecode == TYPE_LSTR: return val.asString()
+ elif typecode == TYPE_ABSTIME: return val.asInt64()
+ elif typecode == TYPE_DELTATIME: return val.asUint64()
+ elif typecode == TYPE_REF: return ObjectId(val.asObjectId())
+ elif typecode == TYPE_BOOL: return val.asBool()
+ elif typecode == TYPE_FLOAT: return val.asFloat()
+ elif typecode == TYPE_DOUBLE: return val.asDouble()
+ elif typecode == TYPE_UUID: return val.asUuid()
+ elif typecode == TYPE_INT8: return val.asInt()
+ elif typecode == TYPE_INT16: return val.asInt()
+ elif typecode == TYPE_INT32: return val.asInt()
+ elif typecode == TYPE_INT64: return val.asInt64()
+ elif typecode == TYPE_MAP: return value_to_dict(val)
+ else:
+ # when TYPE_OBJECT
+ # when TYPE_LIST
+ # when TYPE_ARRAY
+ logging.error( "Unsupported type for get_attr? '%s'" % str(val.getType()) )
+ return None
+
+
+def native_to_qmf(target, value):
+ val = None
+ typecode = None
+ if target.__class__ == qmfengine.Value:
+ val = target
+ typecode = val.getType()
+ else:
+ typecode = target
+ val = qmfengine.Value(typecode)
+
+ if typecode == TYPE_UINT8: val.setUint(value)
+ elif typecode == TYPE_UINT16: val.setUint(value)
+ elif typecode == TYPE_UINT32: val.setUint(value)
+ elif typecode == TYPE_UINT64: val.setUint64(value)
+ elif typecode == TYPE_SSTR:
+ if value: val.setString(value)
+ else: val.setString('')
+ elif typecode == TYPE_LSTR:
+ if value: val.setString(value)
+ else: val.setString('')
+ elif typecode == TYPE_ABSTIME: val.setInt64(value)
+ elif typecode == TYPE_DELTATIME: val.setUint64(value)
+ elif typecode == TYPE_REF: val.setObjectId(value.impl)
+ elif typecode == TYPE_BOOL: val.setBool(value)
+ elif typecode == TYPE_FLOAT: val.setFloat(value)
+ elif typecode == TYPE_DOUBLE: val.setDouble(value)
+ elif typecode == TYPE_UUID: val.setUuid(value)
+ elif typecode == TYPE_INT8: val.setInt(value)
+ elif typecode == TYPE_INT16: val.setInt(value)
+ elif typecode == TYPE_INT32: val.setInt(value)
+ elif typecode == TYPE_INT64: val.setInt64(value)
+ elif typecode == TYPE_MAP: dict_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
+
+
+def pick_qmf_type(value):
+ if value.__class__ == int:
+ if value >= 0:
+ if value < 0x100000000: return TYPE_UINT32
+ return TYPE_UINT64
+ else:
+ if value > -0xffffffff: return TYPE_INT32
+ return TYPE_INT64
+
+ if value.__class__ == long:
+ if value >= 0: return TYPE_UINT64
+ return TYPE_INT64
+
+ if value.__class__ == str:
+ if len(value) < 256: return TYPE_SSTR
+ return TYPE_LSTR
+
+ if value.__class__ == float: return TYPE_DOUBLE
+ if value.__class__ == bool: return TYPE_BOOL
+ if value == None: return TYPE_BOOL
+ if value.__class__ == dict: return TYPE_MAP
+
+ raise "QMF type not known for native type %s" % value.__class__
+
+
+def value_to_dict(val):
+ if not val.isMap(): raise "value_to_dict must be given a map value"
+ mymap = {}
+ for i in range(val.keyCount()):
+ 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():
+ if key.__class__ != str: raise "QMF map key must be a string"
+ typecode = pick_qmf_type(value)
+ val.insert(key, native_to_qmf(typecode, value))
+
+
##==============================================================================
## CONNECTION
##==============================================================================
@@ -293,64 +405,12 @@ class QmfObject(object):
def get_attr(self, name):
val = self._value(name)
- vType = val.getType()
- if vType == TYPE_UINT8: return val.asUint()
- elif vType == TYPE_UINT16: return val.asUint()
- elif vType == TYPE_UINT32: return val.asUint()
- elif vType == TYPE_UINT64: return val.asUint64()
- elif vType == TYPE_SSTR: return val.asString()
- elif vType == TYPE_LSTR: return val.asString()
- elif vType == TYPE_ABSTIME: return val.asInt64()
- elif vType == TYPE_DELTATIME: return val.asUint64()
- elif vType == TYPE_REF: return ObjectId(val.asObjectId())
- elif vType == TYPE_BOOL: return val.asBool()
- elif vType == TYPE_FLOAT: return val.asFloat()
- elif vType == TYPE_DOUBLE: return val.asDouble()
- elif vType == TYPE_UUID: return val.asUuid()
- elif vType == TYPE_INT8: return val.asInt()
- elif vType == TYPE_INT16: return val.asInt()
- elif vType == TYPE_INT32: return val.asInt()
- elif vType == TYPE_INT64: return val.asInt64()
- 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 qmf_to_native(val)
def set_attr(self, name, v):
val = self._value(name)
- vType = val.getType()
- if vType == TYPE_UINT8: return val.setUint(v)
- elif vType == TYPE_UINT16: return val.setUint(v)
- elif vType == TYPE_UINT32: return val.setUint(v)
- elif vType == TYPE_UINT64: return val.setUint64(v)
- elif vType == TYPE_SSTR:
- if v: return val.setString(v)
- else: return val.setString('')
- elif vType == TYPE_LSTR:
- if v: return val.setString(v)
- else: return val.setString('')
- elif vType == TYPE_ABSTIME: return val.setInt64(v)
- elif vType == TYPE_DELTATIME: return val.setUint64(v)
- elif vType == TYPE_REF: return val.setObjectId(v.impl)
- elif vType == TYPE_BOOL: return val.setBool(v)
- elif vType == TYPE_FLOAT: return val.setFloat(v)
- elif vType == TYPE_DOUBLE: return val.setDouble(v)
- elif vType == TYPE_UUID: return val.setUuid(v)
- elif vType == TYPE_INT8: return val.setInt(v)
- elif vType == TYPE_INT16: return val.setInt(v)
- elif vType == TYPE_INT32: return val.setInt(v)
- elif vType == TYPE_INT64: return val.setInt64(v)
- 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
+ native_to_qmf(val, v)
def __getitem__(self, name):
@@ -577,7 +637,8 @@ class Arguments(object):
key_count = self.map.keyCount()
a = 0
while a < key_count:
- self._by_hash[self.map.key(a)] = self.by_key(self.map.key(a))
+ key = self.map.key(a)
+ self._by_hash[key] = qmf_to_native(self.map.byKey(key))
a += 1
@@ -615,70 +676,9 @@ class Arguments(object):
return super.__setattr__(self, name, value)
- def by_key(self, key):
- val = self.map.byKey(key)
- vType = val.getType()
- if vType == TYPE_UINT8: return val.asUint()
- elif vType == TYPE_UINT16: return val.asUint()
- elif vType == TYPE_UINT32: return val.asUint()
- elif vType == TYPE_UINT64: return val.asUint64()
- elif vType == TYPE_SSTR: return val.asString()
- elif vType == TYPE_LSTR: return val.asString()
- elif vType == TYPE_ABSTIME: return val.asInt64()
- elif vType == TYPE_DELTATIME: return val.asUint64()
- elif vType == TYPE_REF: return ObjectId(val.asObjectId())
- elif vType == TYPE_BOOL: return val.asBool()
- elif vType == TYPE_FLOAT: return val.asFloat()
- elif vType == TYPE_DOUBLE: return val.asDouble()
- elif vType == TYPE_UUID: return val.asUuid()
- elif vType == TYPE_INT8: return val.asInt()
- elif vType == TYPE_INT16: return val.asInt()
- elif vType == TYPE_INT32: return val.asInt()
- elif vType == TYPE_INT64: return val.asInt64()
- else:
- # when TYPE_MAP
- # when TYPE_OBJECT
- # when TYPE_LIST
- # when TYPE_ARRAY
- logging.error( "Unsupported Type for Get? '%s'" % str(val.getType()))
- return None
-
-
def set(self, key, value):
val = self.map.byKey(key)
- vType = val.getType()
- if vType == TYPE_UINT8: return val.setUint(value)
- elif vType == TYPE_UINT16: return val.setUint(value)
- elif vType == TYPE_UINT32: return val.setUint(value)
- elif vType == TYPE_UINT64: return val.setUint64(value)
- elif vType == TYPE_SSTR:
- if value:
- return val.setString(value)
- else:
- return val.setString('')
- elif vType == TYPE_LSTR:
- if value:
- return val.setString(value)
- else:
- return val.setString('')
- elif vType == TYPE_ABSTIME: return val.setInt64(value)
- elif vType == TYPE_DELTATIME: return val.setUint64(value)
- elif vType == TYPE_REF: return val.setObjectId(value.impl)
- elif vType == TYPE_BOOL: return val.setBool(value)
- elif vType == TYPE_FLOAT: return val.setFloat(value)
- elif vType == TYPE_DOUBLE: return val.setDouble(value)
- elif vType == TYPE_UUID: return val.setUuid(value)
- elif vType == TYPE_INT8: return val.setInt(value)
- elif vType == TYPE_INT16: return val.setInt(value)
- elif vType == TYPE_INT32: return val.setInt(value)
- elif vType == TYPE_INT64: return val.setInt64(value)
- else:
- # when TYPE_MAP
- # when TYPE_OBJECT
- # when TYPE_LIST
- # when TYPE_ARRAY
- logging.error("Unsupported Type for Set? '%s'" % str(val.getType()))
- return None
+ native_to_qmf(val, value)
diff --git a/qpid/cpp/bindings/qmf/ruby/qmf.rb b/qpid/cpp/bindings/qmf/ruby/qmf.rb
index 857dd64aeb..ea085d1be2 100644
--- a/qpid/cpp/bindings/qmf/ruby/qmf.rb
+++ b/qpid/cpp/bindings/qmf/ruby/qmf.rb
@@ -31,6 +31,112 @@ module Qmf
end
end
+ class Util
+ def qmf_to_native(val)
+ case val.getType
+ when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint
+ when TYPE_UINT64 then val.asUint64
+ when TYPE_SSTR, TYPE_LSTR then val.asString
+ when TYPE_ABSTIME then val.asInt64
+ when TYPE_DELTATIME then val.asUint64
+ when TYPE_REF then ObjectId.new(val.asObjectId)
+ when TYPE_BOOL then val.asBool
+ when TYPE_FLOAT then val.asFloat
+ when TYPE_DOUBLE then val.asDouble
+ when TYPE_UUID then val.asUuid
+ 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_OBJECT
+ when TYPE_LIST
+ when TYPE_ARRAY
+ end
+ end
+
+ def native_to_qmf(target, value)
+ if target.class == Qmfengine::Value
+ val = target
+ typecode = val.getType
+ else
+ typecode = target
+ val = Qmfengine::Value.new(typecode)
+ end
+
+ case typecode
+ when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(value)
+ when TYPE_UINT64 then val.setUint64(value)
+ when TYPE_SSTR, TYPE_LSTR then value ? val.setString(value) : val.setString('')
+ when TYPE_ABSTIME then val.setInt64(value)
+ when TYPE_DELTATIME then val.setUint64(value)
+ when TYPE_REF then val.setObjectId(value.impl)
+ when TYPE_BOOL then value ? val.setBool(value) : val.setBool(0)
+ when TYPE_FLOAT then val.setFloat(value)
+ when TYPE_DOUBLE then val.setDouble(value)
+ when TYPE_UUID then val.setUuid(value)
+ 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_OBJECT
+ when TYPE_LIST
+ when TYPE_ARRAY
+ end
+ return val
+ end
+
+ def pick_qmf_type(value)
+ if value.class == Fixnum
+ if value >= 0
+ return TYPE_UINT32 if value < 0x100000000
+ return TYPE_UINT64
+ else
+ return TYPE_INT32 if value > -0xffffffff
+ return TYPE_INT64
+ end
+ end
+
+ if value.class == Bignum
+ return TYPE_UINT64 if value >= 0
+ return TYPE_INT64
+ end
+
+ if value.class == String
+ return TYPE_SSTR if value.length < 256
+ return TYPE_LSTR
+ end
+
+ return TYPE_DOUBLE if value.class == Float
+
+ return TYPE_BOOL if value.class == TrueClass
+ return TYPE_BOOL if value.class == FalseClass
+ return TYPE_BOOL if value.class == NilClass
+
+ return TYPE_MAP if value.class == Hash
+
+ raise ArgumentError, "QMF type not known for native type #{value.class}"
+ end
+
+ def value_to_dict(val)
+ # Assume val is of type Qmfengine::Value
+ raise ArgumentError, "value_to_dict must be given a map value" if !val.isMap
+ map = {}
+ for i in 0...val.keyCount
+ key = val.key(i)
+ map[key] = qmf_to_native(val.byKey(key))
+ end
+ return map
+ end
+
+ def dict_to_value(val, map)
+ map.each do |key, value|
+ raise ArgumentError, "QMF map key must be a string" if key.class != String
+ typecode = pick_qmf_type(value)
+ val.insert(key, native_to_qmf(typecode, value))
+ end
+ end
+ end
+
+ $util = Util.new
+
##==============================================================================
## CONNECTION
##==============================================================================
@@ -246,46 +352,12 @@ module Qmf
def get_attr(name)
val = value(name)
- case val.getType
- when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint
- when TYPE_UINT64 then val.asUint64
- when TYPE_SSTR, TYPE_LSTR then val.asString
- when TYPE_ABSTIME then val.asInt64
- when TYPE_DELTATIME then val.asUint64
- when TYPE_REF then ObjectId.new(val.asObjectId)
- when TYPE_BOOL then val.asBool
- when TYPE_FLOAT then val.asFloat
- when TYPE_DOUBLE then val.asDouble
- when TYPE_UUID then val.asUuid
- when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt
- when TYPE_INT64 then val.asInt64
- when TYPE_MAP
- when TYPE_OBJECT
- when TYPE_LIST
- when TYPE_ARRAY
- end
+ $util.qmf_to_native(val)
end
def set_attr(name, v)
val = value(name)
- case val.getType
- when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(v)
- when TYPE_UINT64 then val.setUint64(v)
- when TYPE_SSTR, TYPE_LSTR then v ? val.setString(v) : val.setString('')
- when TYPE_ABSTIME then val.setInt64(v)
- when TYPE_DELTATIME then val.setUint64(v)
- when TYPE_REF then val.setObjectId(v.impl)
- when TYPE_BOOL then v ? val.setBool(v) : val.setBool(0)
- when TYPE_FLOAT then val.setFloat(v)
- when TYPE_DOUBLE then val.setDouble(v)
- when TYPE_UUID then val.setUuid(v)
- when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(v)
- when TYPE_INT64 then val.setInt64(v)
- when TYPE_MAP
- when TYPE_OBJECT
- when TYPE_LIST
- when TYPE_ARRAY
- end
+ $util.native_to_qmf(val, v)
end
def [](name)
@@ -488,7 +560,8 @@ module Qmf
key_count = @map.keyCount
a = 0
while a < key_count
- @by_hash[@map.key(a)] = by_key(@map.key(a))
+ key = @map.key(a)
+ @by_hash[key] = $util.qmf_to_native(@map.byKey(key))
a += 1
end
end
@@ -514,48 +587,9 @@ module Qmf
super.method_missing(name, args)
end
- def by_key(key)
- val = @map.byKey(key)
- case val.getType
- when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint
- when TYPE_UINT64 then val.asUint64
- when TYPE_SSTR, TYPE_LSTR then val.asString
- when TYPE_ABSTIME then val.asInt64
- when TYPE_DELTATIME then val.asUint64
- when TYPE_REF then ObjectId.new(val.asObjectId)
- when TYPE_BOOL then val.asBool
- when TYPE_FLOAT then val.asFloat
- when TYPE_DOUBLE then val.asDouble
- when TYPE_UUID then val.asUuid
- when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt
- when TYPE_INT64 then val.asInt64
- when TYPE_MAP
- when TYPE_OBJECT
- when TYPE_LIST
- when TYPE_ARRAY
- end
- end
-
def set(key, value)
val = @map.byKey(key)
- case val.getType
- when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(value)
- when TYPE_UINT64 then val.setUint64(value)
- when TYPE_SSTR, TYPE_LSTR then value ? val.setString(value) : val.setString('')
- when TYPE_ABSTIME then val.setInt64(value)
- when TYPE_DELTATIME then val.setUint64(value)
- when TYPE_REF then val.setObjectId(value.impl)
- when TYPE_BOOL then value ? val.setBool(value) : val.setBool(0)
- when TYPE_FLOAT then val.setFloat(value)
- when TYPE_DOUBLE then val.setDouble(value)
- when TYPE_UUID then val.setUuid(value)
- when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(value)
- when TYPE_INT64 then val.setInt64(value)
- when TYPE_MAP
- when TYPE_OBJECT
- when TYPE_LIST
- when TYPE_ARRAY
- end
+ $util.native_to_qmf(val, value)
end
end
diff --git a/qpid/cpp/bindings/qmf/ruby/ruby.i b/qpid/cpp/bindings/qmf/ruby/ruby.i
index b7fed403bd..0101861100 100644
--- a/qpid/cpp/bindings/qmf/ruby/ruby.i
+++ b/qpid/cpp/bindings/qmf/ruby/ruby.i
@@ -76,7 +76,7 @@
if (TYPE($input) == T_BIGNUM)
$1 = NUM2ULL($input);
else
- $1 = (uint64_t) FIX2LONG($input);
+ $1 = (uint64_t) FIX2ULONG($input);
}
%typemap (out) uint64_t
diff --git a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
index adf91a8b66..0be779994a 100755
--- a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
+++ b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
@@ -43,6 +43,8 @@ class Model
@parent_class.add_property(Qmf::SchemaProperty.new("sstrval", Qmf::TYPE_SSTR))
@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_statistic(Qmf::SchemaStatistic.new("queryCount", Qmf::TYPE_UINT32, :unit => "query", :desc => "Query count"))
method = Qmf::SchemaMethod.new("echo", :desc => "Check responsiveness of the agent object")
@@ -53,6 +55,11 @@ class Model
method.add_argument(Qmf::SchemaArgument.new("test", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN))
@parent_class.add_method(method)
+ method = Qmf::SchemaMethod.new("set_map", :desc => "Set the map value in the object")
+ method.add_argument(Qmf::SchemaArgument.new("value", Qmf::TYPE_MAP, :dir => Qmf::DIR_IN))
+ method.add_argument(Qmf::SchemaArgument.new("output", Qmf::TYPE_MAP, :dir => Qmf::DIR_OUT))
+ @parent_class.add_method(method)
+
method = Qmf::SchemaMethod.new("set_short_string", :desc => "Set the short string value in the object")
method.add_argument(Qmf::SchemaArgument.new("value", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN_OUT))
@parent_class.add_method(method)
@@ -101,19 +108,37 @@ class App < Qmf::AgentHandler
if name == "echo"
@agent.method_response(context, 0, "OK", args)
+ elsif name == "set_map"
+
+ map = args['value']
+
+ map['added'] = 'Added Text'
+ args['output'] = map
+
elsif name == "set_numerics"
if args['test'] == "big"
@parent.uint64val = 0x9494949449494949
@parent.uint32val = 0xa5a55a5a
@parent.uint16val = 0xb66b
- @parent.uint8val = 0xc7
+ @parent.uint8val = 0xc7
@parent.int64val = 1000000000000000000
@parent.int32val = 1000000000
@parent.int16val = 10000
@parent.int8val = 100
+ @parent.mapval = {'u64' => @parent.uint64val,
+ 'u32' => @parent.uint32val,
+ 'u16' => @parent.uint16val,
+ 'u8' => @parent.uint8val,
+ 'i64' => @parent.int64val,
+ 'i32' => @parent.int32val,
+ 'i16' => @parent.int16val,
+ 'i8' => @parent.int8val,
+ 'sstr' => "Short String",
+ 'map' => {'first' => 'FIRST', 'second' => 'SECOND'}}
+
elsif args['test'] == "small"
@parent.uint64val = 4
@parent.uint32val = 5
diff --git a/qpid/cpp/bindings/qmf/tests/python_agent.py b/qpid/cpp/bindings/qmf/tests/python_agent.py
index 0f5ffe5b8a..c42273d7b2 100644
--- a/qpid/cpp/bindings/qmf/tests/python_agent.py
+++ b/qpid/cpp/bindings/qmf/tests/python_agent.py
@@ -41,6 +41,12 @@ class Model:
self.parent_class.add_property(qmf.SchemaProperty("int16val", qmf.TYPE_INT16))
self.parent_class.add_property(qmf.SchemaProperty("int8val", qmf.TYPE_INT8))
+ self.parent_class.add_property(qmf.SchemaProperty("sstrval", qmf.TYPE_SSTR))
+ 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_statistic(qmf.SchemaStatistic("queryCount", qmf.TYPE_UINT32, {"unit":"query", "desc":"Query count"}))
_method = qmf.SchemaMethod("echo", {"desc":"Check responsiveness of the agent object"})
@@ -51,6 +57,19 @@ class Model:
_method.add_argument(qmf.SchemaArgument("test", qmf.TYPE_SSTR, {"dir":qmf.DIR_IN}))
self.parent_class.add_method(_method)
+ _method = qmf.SchemaMethod("set_map", {"desc":"Set the map value in the object"})
+ _method.add_argument(qmf.SchemaArgument("value", qmf.TYPE_MAP, {"dir":qmf.DIR_IN}))
+ _method.add_argument(qmf.SchemaArgument("output", qmf.TYPE_MAP, {"dir":qmf.DIR_OUT}))
+ self.parent_class.add_method(_method)
+
+ _method = qmf.SchemaMethod("set_short_string", {"desc":"Set the short string value in the object"})
+ _method.add_argument(qmf.SchemaArgument("value", qmf.TYPE_SSTR, {"dir":qmf.DIR_IN_OUT}))
+ self.parent_class.add_method(_method)
+
+ _method = qmf.SchemaMethod("set_long_string", {"desc":"Set the long string value in the object"})
+ _method.add_argument(qmf.SchemaArgument("value", qmf.TYPE_LSTR, {"dir":qmf.DIR_IN_OUT}))
+ self.parent_class.add_method(_method)
+
_method = qmf.SchemaMethod("create_child", {"desc":"Create a new child object"})
_method.add_argument(qmf.SchemaArgument("child_name", qmf.TYPE_LSTR, {"dir":qmf.DIR_IN}))
_method.add_argument(qmf.SchemaArgument("child_ref", qmf.TYPE_REF, {"dir":qmf.DIR_OUT}))
@@ -97,6 +116,12 @@ class App(qmf.AgentHandler):
if name == "echo":
self._agent.method_response(context, 0, "OK", args)
+ elif name == "set_map":
+ map = args['value']
+ map['added'] = "Added Text"
+ args['output'] = map
+ self._agent.method_response(context, 0, "OK", args)
+
elif name == "set_numerics":
_retCode = 0
_retText = "OK"
@@ -115,6 +140,17 @@ class App(qmf.AgentHandler):
self._parent["int16val"] = 10000
self._parent.set_attr("int8val", 100)
+ self._parent.set_attr("mapval", {'u64' : self._parent['uint64val'],
+ 'u32' : self._parent['uint32val'],
+ 'u16' : self._parent['uint16val'],
+ 'u8' : self._parent['uint8val'],
+ 'i64' : self._parent['int64val'],
+ 'i32' : self._parent['int32val'],
+ 'i16' : self._parent['int16val'],
+ 'i8' : self._parent['int8val'],
+ 'sstr' : "Short String",
+ 'map' : {'first' : 'FIRST', 'second' : 'SECOND'}})
+
## Test the __getattr__ implementation:
## @todo: remove once python_client implements this
## form of property access
@@ -150,6 +186,14 @@ class App(qmf.AgentHandler):
self._agent.method_response(context, _retCode, _retText, args)
+ elif name == "set_short_string":
+ self._parent.set_attr('sstrval', args['value'])
+ self._agent.method_response(context, 0, "OK", args)
+
+ elif name == "set_long_string":
+ self._parent.set_attr('lstrval', args['value'])
+ self._agent.method_response(context, 0, "OK", args)
+
elif name == "create_child":
#
# Instantiate an object based on the Child Schema Class
@@ -199,7 +243,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()) == 10
+ assert len(self._parent.properties()) == 13
assert len(self._parent.statistics()) == 1
self._parent.set_attr("name", "Parent One")
diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
index c5c7b141dd..3a771aaafd 100755
--- a/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
+++ b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
@@ -177,6 +177,44 @@ class ConsoleTest < ConsoleTestBase
end
end
+ def test_C_basic_types_map
+ parent = @qmfc.object(:class =>"parent")
+ assert(parent, "Number of parent objects")
+
+ result = parent.set_numerics("big")
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.text, "OK", "Method Response Text")
+
+ parent.update
+
+ map = parent.mapval
+
+ assert_equal(map['u64'], 0x9494949449494949)
+ assert_equal(map['u32'], 0xA5A55A5A)
+ assert_equal(map['u16'], 0xB66B)
+ assert_equal(map['u8'], 0xC7)
+
+ assert_equal(map['i64'], 1000000000000000000)
+ assert_equal(map['i32'], 1000000000)
+ assert_equal(map['i16'], 10000)
+ assert_equal(map['i8'], 100)
+
+ assert_equal(map['sstr'], "Short String")
+
+ submap = map['map']
+ assert_equal(submap['first'], "FIRST")
+ assert_equal(submap['second'], "SECOND")
+
+ result = parent.set_map({'first' => 'FIRST', 'sub' => {'subfirst' => 25}})
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.text, "OK", "Method Response Text")
+
+ rmap = result.args.output
+ assert_equal(rmap['first'], "FIRST")
+ assert_equal(rmap['sub']['subfirst'], 25)
+ assert_equal(rmap['added'], 'Added Text')
+ end
+
def test_D_userid_for_method
parent = @qmfc.object(:class => "parent")
assert(parent, "Number of parent objects")
diff --git a/qpid/cpp/bindings/qmf/tests/run_interop_tests b/qpid/cpp/bindings/qmf/tests/run_interop_tests
index b5545d736d..1669fe0189 100755
--- a/qpid/cpp/bindings/qmf/tests/run_interop_tests
+++ b/qpid/cpp/bindings/qmf/tests/run_interop_tests
@@ -101,6 +101,18 @@ if test -d ${PYTHON_DIR} ; then
echo "FAIL qmf interop tests (Ruby Console/Ruby Agent)";
TESTS_FAILED=1
fi
+
+ if test -d ${PYTHON_LIB_DIR} ; then
+ echo " Python Agent (external storage) vs. Ruby Console"
+ start_python_agent
+ ruby -I${MY_DIR} -I${MY_DIR}/../ruby -I${RUBY_LIB_DIR} ${MY_DIR}/ruby_console_test.rb localhost $BROKER_PORT $@
+ RETCODE=$?
+ stop_python_agent
+ if test x$RETCODE != x0; then
+ echo "FAIL qmf interop tests (Ruby Console/Python Agent)";
+ TESTS_FAILED=1
+ fi
+ fi
fi
# Also against the Pure-Python console:
diff --git a/qpid/cpp/include/qpid/framing/FieldValue.h b/qpid/cpp/include/qpid/framing/FieldValue.h
index 60a887761f..7b4dee1529 100644
--- a/qpid/cpp/include/qpid/framing/FieldValue.h
+++ b/qpid/cpp/include/qpid/framing/FieldValue.h
@@ -83,7 +83,7 @@ class FieldValue {
FieldValue(): data(0) {};
// Default assignment operator is fine
void setType(uint8_t type);
- QPID_COMMON_EXTERN uint8_t getType();
+ QPID_COMMON_EXTERN uint8_t getType() const;
Data& getData() { return *data; }
uint32_t encodedSize() const { return 1 + data->encodedSize(); };
bool empty() const { return data.get() == 0; }
diff --git a/qpid/cpp/src/qmf/engine/ValueImpl.cpp b/qpid/cpp/src/qmf/engine/ValueImpl.cpp
index 1949d4b946..b1c027520f 100644
--- a/qpid/cpp/src/qmf/engine/ValueImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/ValueImpl.cpp
@@ -19,16 +19,19 @@
#include "qmf/engine/ValueImpl.h"
#include <qpid/framing/FieldTable.h>
+#include <qpid/framing/FieldValue.h>
using namespace std;
using namespace qmf::engine;
using qpid::framing::Buffer;
+using qpid::framing::FieldTable;
+using qpid::framing::FieldValue;
ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t)
{
uint64_t first;
uint64_t second;
- qpid::framing::FieldTable ft;
+ FieldTable ft;
switch (typecode) {
case TYPE_UINT8 : value.u32 = (uint32_t) buf.getOctet(); break;
@@ -55,6 +58,7 @@ ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t)
case TYPE_MAP:
ft.decode(buf);
+ initMap(ft);
break;
case TYPE_LIST:
@@ -90,8 +94,111 @@ ValueImpl::~ValueImpl()
{
}
+void ValueImpl::initMap(const FieldTable& ft)
+{
+ for (FieldTable::ValueMap::const_iterator iter = ft.begin();
+ iter != ft.end(); iter++) {
+ const string& name(iter->first);
+ const FieldValue& fvalue(*iter->second);
+ uint8_t amqType = fvalue.getType();
+
+ if (amqType == 0x32) {
+ Value* subval(new Value(TYPE_UINT64));
+ subval->setUint64(fvalue.get<int64_t>());
+ insert(name.c_str(), 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;
+ }
+ insert(name.c_str(), subval);
+ } else if ((amqType & 0xCF) == 0x01) {
+ Value* subval(new Value(TYPE_INT64));
+ subval->setInt64(fvalue.get<int64_t>());
+ insert(name.c_str(), subval);
+ } else if (amqType == 0x85 || amqType == 0x95) {
+ Value* subval(new Value(TYPE_LSTR));
+ subval->setString(fvalue.get<string>().c_str());
+ insert(name.c_str(), subval);
+ } else if (amqType == 0x23 || amqType == 0x33) {
+ Value* subval(new Value(TYPE_DOUBLE));
+ subval->setDouble(fvalue.get<double>());
+ insert(name.c_str(), subval);
+ } else {
+ FieldTable subFt;
+ bool valid = qpid::framing::getEncodedValue<FieldTable>(iter->second, subFt);
+ if (valid) {
+ Value* subval(new Value(TYPE_MAP));
+ subval->impl->initMap(subFt);
+ insert(name.c_str(), subval);
+ }
+ }
+ }
+}
+
+void ValueImpl::mapToFieldTable(FieldTable& ft) const
+{
+ FieldTable subFt;
+
+ for (map<string, Value>::const_iterator iter = mapVal.begin();
+ iter != mapVal.end(); iter++) {
+ const string& name(iter->first);
+ const Value& subval(iter->second);
+
+ switch (subval.getType()) {
+ case TYPE_UINT8:
+ case TYPE_UINT16:
+ case TYPE_UINT32:
+ ft.setUInt64(name, (uint64_t) subval.asUint());
+ break;
+ case TYPE_UINT64:
+ case TYPE_DELTATIME:
+ ft.setUInt64(name, subval.asUint64());
+ break;
+ case TYPE_SSTR:
+ case TYPE_LSTR:
+ ft.setString(name, subval.asString());
+ break;
+ case TYPE_INT64:
+ case TYPE_ABSTIME:
+ ft.setInt64(name, subval.asInt64());
+ break;
+ case TYPE_BOOL:
+ ft.setInt(name, subval.asBool() ? 1 : 0);
+ break;
+ case TYPE_FLOAT:
+ ft.setFloat(name, subval.asFloat());
+ break;
+ case TYPE_DOUBLE:
+ ft.setDouble(name, subval.asDouble());
+ break;
+ case TYPE_INT8:
+ case TYPE_INT16:
+ case TYPE_INT32:
+ ft.setInt(name, subval.asInt());
+ break;
+ case TYPE_MAP:
+ subFt.clear();
+ subval.impl->mapToFieldTable(subFt);
+ ft.setTable(name, subFt);
+ break;
+ case TYPE_LIST:
+ case TYPE_ARRAY:
+ case TYPE_OBJECT:
+ case TYPE_UUID:
+ case TYPE_REF:
+ default:
+ break;
+ }
+ }
+ }
+
void ValueImpl::encode(Buffer& buf) const
{
+ FieldTable ft;
+
switch (typecode) {
case TYPE_UINT8 : buf.putOctet((uint8_t) value.u32); break;
case TYPE_UINT16 : buf.putShort((uint16_t) value.u32); break;
@@ -110,7 +217,10 @@ void ValueImpl::encode(Buffer& buf) const
case TYPE_INT64 : buf.putLongLong(value.s64); break;
case TYPE_UUID : buf.putBin128(value.uuidVal); break;
case TYPE_REF : refVal.impl->encode(buf); break;
- case TYPE_MAP: // TODO
+ case TYPE_MAP:
+ mapToFieldTable(ft);
+ ft.encode(buf);
+ break;
case TYPE_LIST:
case TYPE_ARRAY:
case TYPE_OBJECT:
@@ -127,7 +237,7 @@ bool ValueImpl::keyInMap(const char* key) const
Value* ValueImpl::byKey(const char* key)
{
if (keyInMap(key)) {
- map<std::string, Value>::iterator iter = mapVal.find(key);
+ map<string, Value>::iterator iter = mapVal.find(key);
if (iter != mapVal.end())
return &iter->second;
}
@@ -137,7 +247,7 @@ Value* ValueImpl::byKey(const char* key)
const Value* ValueImpl::byKey(const char* key) const
{
if (keyInMap(key)) {
- map<std::string, Value>::const_iterator iter = mapVal.find(key);
+ map<string, Value>::const_iterator iter = mapVal.find(key);
if (iter != mapVal.end())
return &iter->second;
}
@@ -157,7 +267,7 @@ void ValueImpl::insert(const char* key, Value* val)
const char* ValueImpl::key(uint32_t idx) const
{
- map<std::string, Value>::const_iterator iter = mapVal.begin();
+ map<string, Value>::const_iterator iter = mapVal.begin();
for (uint32_t i = 0; i < idx; i++) {
if (iter == mapVal.end())
break;
diff --git a/qpid/cpp/src/qmf/engine/ValueImpl.h b/qpid/cpp/src/qmf/engine/ValueImpl.h
index b6adae5d93..84b0e768e6 100644
--- a/qpid/cpp/src/qmf/engine/ValueImpl.h
+++ b/qpid/cpp/src/qmf/engine/ValueImpl.h
@@ -30,6 +30,12 @@
#include <vector>
#include <boost/shared_ptr.hpp>
+namespace qpid {
+namespace framing {
+ class FieldTable;
+}
+}
+
namespace qmf {
namespace engine {
@@ -142,6 +148,10 @@ namespace engine {
Value* arrayItem(uint32_t idx);
void appendToArray(Value* val);
void deleteArrayItem(uint32_t idx);
+
+ private:
+ void mapToFieldTable(qpid::framing::FieldTable& ft) const;
+ void initMap(const qpid::framing::FieldTable& ft);
};
}
}
diff --git a/qpid/cpp/src/qpid/framing/FieldValue.cpp b/qpid/cpp/src/qpid/framing/FieldValue.cpp
index 5bac931b83..9c5c0c36a2 100644
--- a/qpid/cpp/src/qpid/framing/FieldValue.cpp
+++ b/qpid/cpp/src/qpid/framing/FieldValue.cpp
@@ -28,7 +28,7 @@
namespace qpid {
namespace framing {
-uint8_t FieldValue::getType()
+uint8_t FieldValue::getType() const
{
return typeOctet;
}