Author: tross
Date: Tue Jan  5 19:45:28 2010
New Revision: 896191

URL: http://svn.apache.org/viewvc?rev=896191&view=rev
Log:
Added handling of MAP values for the wrapped QMF interfaces.

Modified:
    qpid/trunk/qpid/cpp/bindings/qmf/python/qmf.py
    qpid/trunk/qpid/cpp/bindings/qmf/ruby/qmf.rb
    qpid/trunk/qpid/cpp/bindings/qmf/ruby/ruby.i
    qpid/trunk/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
    qpid/trunk/qpid/cpp/bindings/qmf/tests/python_agent.py
    qpid/trunk/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
    qpid/trunk/qpid/cpp/bindings/qmf/tests/run_interop_tests
    qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h
    qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.cpp
    qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.h
    qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp

Modified: qpid/trunk/qpid/cpp/bindings/qmf/python/qmf.py
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/python/qmf.py?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/python/qmf.py (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/python/qmf.py Tue Jan  5 19:45:28 2010
@@ -35,6 +35,118 @@
 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 @@
     
     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 @@
         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 @@
         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)
 
 
 

Modified: qpid/trunk/qpid/cpp/bindings/qmf/ruby/qmf.rb
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/ruby/qmf.rb?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/ruby/qmf.rb (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/ruby/qmf.rb Tue Jan  5 19:45:28 2010
@@ -31,6 +31,112 @@
     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 @@
 
     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 @@
       key_count = @map.keyCount
       a = 0
       while a < key_count
-        @[email protected](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 @@
       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
 

Modified: qpid/trunk/qpid/cpp/bindings/qmf/ruby/ruby.i
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/ruby/ruby.i?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/ruby/ruby.i (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/ruby/ruby.i Tue Jan  5 19:45:28 2010
@@ -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

Modified: qpid/trunk/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/tests/agent_ruby.rb?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/tests/agent_ruby.rb (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/tests/agent_ruby.rb Tue Jan  5 19:45:28 
2010
@@ -43,6 +43,8 @@
     @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 @@
     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 @@
     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

Modified: qpid/trunk/qpid/cpp/bindings/qmf/tests/python_agent.py
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/tests/python_agent.py?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/tests/python_agent.py (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/tests/python_agent.py Tue Jan  5 19:45:28 
2010
@@ -41,6 +41,12 @@
         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 @@
         _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 @@
         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 @@
                 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 @@
 
             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 @@
 
         ## @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")

Modified: qpid/trunk/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb Tue Jan  5 
19:45:28 2010
@@ -177,6 +177,44 @@
     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")

Modified: qpid/trunk/qpid/cpp/bindings/qmf/tests/run_interop_tests
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qmf/tests/run_interop_tests?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qmf/tests/run_interop_tests (original)
+++ qpid/trunk/qpid/cpp/bindings/qmf/tests/run_interop_tests Tue Jan  5 
19:45:28 2010
@@ -101,6 +101,18 @@
             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:

Modified: qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h (original)
+++ qpid/trunk/qpid/cpp/include/qpid/framing/FieldValue.h Tue Jan  5 19:45:28 
2010
@@ -83,7 +83,7 @@
     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; }

Modified: qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.cpp?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.cpp Tue Jan  5 19:45:28 2010
@@ -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 @@
 
     case TYPE_MAP:
         ft.decode(buf);
+        initMap(ft);
         break;
 
     case TYPE_LIST:
@@ -90,8 +94,111 @@
 {
 }
 
+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 @@
     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 @@
 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 @@
 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 @@
 
 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;

Modified: qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.h?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.h (original)
+++ qpid/trunk/qpid/cpp/src/qmf/engine/ValueImpl.h Tue Jan  5 19:45:28 2010
@@ -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 @@
         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);
     };
 }
 }

Modified: qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp?rev=896191&r1=896190&r2=896191&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/framing/FieldValue.cpp Tue Jan  5 19:45:28 2010
@@ -28,7 +28,7 @@
 namespace qpid {
 namespace framing {
 
-uint8_t FieldValue::getType()
+uint8_t FieldValue::getType() const
 {
     return typeOctet;
 }



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:[email protected]

Reply via email to