summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorTed Ross <tross@apache.org>2010-05-14 14:01:35 +0000
committerTed Ross <tross@apache.org>2010-05-14 14:01:35 +0000
commitec1bb7110f50d2e30b7d636b9f863846d5e22676 (patch)
tree95f0178c5e1d2721d649dbbc021b2df8a0515e2c /cpp
parent854062d73c485027f2f40abac159cb19e85c0dca (diff)
downloadqpid-python-ec1bb7110f50d2e30b7d636b9f863846d5e22676.tar.gz
QPID-2589 - Patch from Chuck Rolke that exposes structured message content (map/list).
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@944263 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rw-r--r--cpp/bindings/qpid/dotnet/src/Message.cpp466
-rw-r--r--cpp/bindings/qpid/dotnet/src/Message.h63
2 files changed, 528 insertions, 1 deletions
diff --git a/cpp/bindings/qpid/dotnet/src/Message.cpp b/cpp/bindings/qpid/dotnet/src/Message.cpp
index 90ca4e8915..a3e966ec48 100644
--- a/cpp/bindings/qpid/dotnet/src/Message.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Message.cpp
@@ -20,10 +20,13 @@
#include <windows.h>
#include <msclr\lock.h>
#include <oletx2xa.h>
+#include <typeinfo.h>
#include <string>
#include <limits>
+#include <iostream>
#include "qpid/messaging/Message.h"
+#include "qpid/types/Variant.h"
#include "QpidMarshal.h"
#include "Message.h"
@@ -39,16 +42,75 @@ namespace messaging {
// This constructor is used to create a message from bytes to put into the message
Message::Message(System::String ^ bytes) :
+ aVMap(gcnew VMap()),
+ aVList(gcnew VList()),
+ pVMapType(aVMap.GetType()),
+ pVListType(aVList.GetType()),
messagep(new ::qpid::messaging::Message(QpidMarshal::ToNative(bytes)))
{
}
// This constructor creates a message from a native received message
Message::Message(::qpid::messaging::Message * msgp) :
+ aVMap(gcnew VMap()),
+ aVList(gcnew VList()),
+ pVMapType(aVMap.GetType()),
+ pVListType(aVList.GetType()),
messagep(msgp)
{
}
+
+ Message::Message(System::Object ^ objp) :
+ aVMap(gcnew VMap()),
+ aVList(gcnew VList()),
+ pVMapType(aVMap.GetType()),
+ pVListType(aVList.GetType()),
+ messagep(new ::qpid::messaging::Message(QpidMarshal::ToNative("")))
+ {
+ ::qpid::types::Variant * variantp = 0;
+ std::string * variantsp = 0;
+
+ if (objIsMap(objp))
+ {
+ // Create a mapped message using given dictionary
+
+ // Allocate a map
+ ::qpid::types::Variant::Map newMap;
+
+ // Add the map variables to the map
+ Encode(newMap, (VMap ^)objp);
+
+ // Set message content type
+ messagep->setContentType("ampq/map");
+
+ // Insert the map into the message
+ ::qpid::messaging::encode(newMap, *messagep, QpidMarshal::ToNative("amqp/map"));
+ }
+ else if (objIsList(objp))
+ {
+ // Create a list message using given list
+
+ // Allocate a list
+ ::qpid::types::Variant::List newList;
+
+ // Add the list variables to the list
+ Encode(newList, (VList ^)objp);
+
+ // Set message content type
+ messagep->setContentType("ampq/list");
+
+ // Insert the list into the message
+ ::qpid::messaging::encode(newList, *messagep, QpidMarshal::ToNative("amqp/list"));
+ }
+ else
+ {
+ // Create a binary string message
+ messagep->setContent(QpidMarshal::ToNative(objp->ToString()));
+ }
+ }
+
+
// Destructor
Message::~Message()
{
@@ -79,6 +141,199 @@ namespace messaging {
}
}
+
+ //
+ // The given object is a Dictionary.
+ // Add its elements to the qpid map.
+ //
+ void Message::Encode(::qpid::types::Variant::Map & theMapp,
+ VMap ^ theObjp)
+ {
+ // iterate the items, converting each to a variant and adding to the map
+ for each (System::Collections::Generic::KeyValuePair<System::String^, System::Object^> kvp in theObjp)
+ {
+ if (objIsMap(kvp.Value))
+ {
+ // Recurse on inner map
+ // Allocate a map
+ ::qpid::types::Variant::Map newMap;
+
+ // Add the map variables to the map
+ Encode(newMap, (VMap ^)kvp.Value);
+
+ // Create a variant entry for the inner map
+ std::auto_ptr<::qpid::types::Variant> newVariantp(new ::qpid::types::Variant(newMap));
+
+ // Get map's name
+ std::string entryName = QpidMarshal::ToNative(kvp.Key);
+
+ // Add inner map to outer map
+ theMapp.insert(std::make_pair<std::string, ::qpid::types::Variant>(entryName, *newVariantp));
+ }
+ else if (objIsList(kvp.Value))
+ {
+ // Recurse on inner list
+ // Allocate a list
+ ::qpid::types::Variant::List newList;
+
+ // Add the List variables to the list
+ Encode(newList, (VList ^)kvp.Value);
+
+ // Create a variant entry for the inner map
+ ::qpid::types::Variant::List newVariant(newList);
+
+ //std::auto_ptr<::qpid::types::Variant> newVariantp(new ::qpid::types::Variant(newList));
+
+ // Get list's name
+ std::string entryName = QpidMarshal::ToNative(kvp.Key);
+
+ // Add inner list to outer map
+ theMapp.insert(std::make_pair<std::string, ::qpid::types::Variant>(entryName, newVariant));
+ }
+ else
+ {
+ // Add a simple native type to map
+ ::qpid::types::Variant entryValue;
+ EncodeObject(kvp.Value, entryValue);
+ std::string entryName = QpidMarshal::ToNative(kvp.Key);
+ theMapp.insert(std::make_pair<std::string, ::qpid::types::Variant>(entryName, entryValue));
+ }
+ }
+ }
+
+
+
+ //
+ // The given object is a List.
+ // Add its elements to the qpid list.
+ //
+ void Message::Encode(::qpid::types::Variant::List & theListp,
+ VList ^ theObjp)
+ {
+ // iterate the items, converting each to a variant and adding to the map
+ for each (System::Object ^ listObj in theObjp)
+ {
+ if (objIsMap(listObj))
+ {
+ // Recurse on inner map
+ // Allocate a map
+ ::qpid::types::Variant::Map newMap;
+
+ // Add the map variables to the map
+ Encode(newMap, (VMap ^)listObj);
+
+ // Create a variant entry for the inner map
+ std::auto_ptr<::qpid::types::Variant> newVariantp(new ::qpid::types::Variant(newMap));
+
+ // Add inner map to outer list
+ theListp.push_back(*newVariantp);
+ }
+ else if (objIsList(listObj))
+ {
+ // Recurse on inner list
+ // Allocate a list
+ ::qpid::types::Variant::List newList;
+
+ // Add the List variables to the list
+ Encode(newList, (VList ^)listObj);
+
+ // Create a variant entry for the inner list
+ std::auto_ptr<::qpid::types::Variant> newVariantp(new ::qpid::types::Variant(newList));
+
+ // Add inner list to outer list
+ theListp.push_back(*newVariantp);
+ }
+ else
+ {
+ // Add a simple native type to list
+ ::qpid::types::Variant entryValue;
+ EncodeObject(listObj, entryValue);
+ theListp.push_back(entryValue);
+ }
+ }
+ }
+
+
+
+ //
+ // Returns a variant representing simple native type object.
+ // Not to be called for Map/List objects.
+ //
+ void Message::EncodeObject(System::Object ^ theObjp,
+ ::qpid::types::Variant & targetp)
+ {
+ System::Type ^ typeP = (*theObjp).GetType();
+ System::TypeCode typeCode = System::Type::GetTypeCode( typeP );
+
+ switch (typeCode)
+ {
+ case System::TypeCode::Boolean :
+ targetp = System::Convert::ToBoolean(theObjp);
+ break;
+
+ case System::TypeCode::Byte :
+ targetp = System::Convert::ToByte(theObjp);
+ break;
+
+ case System::TypeCode::UInt16 :
+ targetp = System::Convert::ToUInt16(theObjp);
+ break;
+
+ case System::TypeCode::UInt32 :
+ targetp = System::Convert::ToUInt32(theObjp);
+ break;
+
+ case System::TypeCode::UInt64 :
+ targetp = System::Convert::ToUInt64(theObjp);
+ break;
+
+ case System::TypeCode::Char :
+ case System::TypeCode::SByte :
+ targetp = System::Convert::ToSByte(theObjp);
+ break;
+
+ case System::TypeCode::Int16 :
+ targetp = System::Convert::ToInt16(theObjp);
+ break;
+
+ case System::TypeCode::Int32 :
+ targetp = System::Convert::ToInt32(theObjp);
+ break;
+
+ case System::TypeCode::Int64 :
+ targetp = System::Convert::ToInt64(theObjp);
+ break;
+
+ case System::TypeCode::Single :
+ targetp = System::Convert::ToSingle(theObjp);
+ break;
+
+ case System::TypeCode::Double :
+ targetp = System::Convert::ToDouble(theObjp);
+ break;
+
+ case System::TypeCode::String :
+ {
+ std::string rString;
+ System::String ^ rpString;
+
+ rpString = System::Convert::ToString(theObjp);
+ rString = QpidMarshal::ToNative(rpString);
+ targetp = rString;
+ }
+ break;
+
+
+ default:
+
+ throw gcnew System::NotImplementedException();
+
+ }
+ }
+
+
+ // Properties...
+
//void Message::setReplyTo(System::String ^ address)
//{
// messagep->setReplyTo(QpidMarshal::ToNative(address));
@@ -199,4 +454,215 @@ namespace messaging {
return gcnew String(messagep->getContent().c_str());
}
+
+ //
+ // User wants to extract a Dictionary from the message
+ //
+ void Message::getContent(System::Collections::Generic::Dictionary<
+ System::String^,
+ System::Object^> ^ dict)
+ {
+ // Extract the message map from the message
+ ::qpid::types::Variant::Map map;
+
+ ::qpid::messaging::decode(*messagep, map, QpidMarshal::ToNative("amqp/map"));
+
+ Decode(dict, map);
+ }
+
+
+ // Given a user Dictionary and a qpid map,
+ // extract the qpid elements and put them into the dictionary.
+ //
+ void Message::Decode(VMap ^ dict, ::qpid::types::Variant::Map & map)
+ {
+ // For each object in the message map,
+ // create a .NET object and add it to the dictionary.
+ for (::qpid::types::Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) {
+ // Get the name
+ System::String ^ elementName = gcnew String(i->first.c_str());
+
+ ::qpid::types::Variant variant = i->second;
+ ::qpid::types::VariantType vType = variant.getType();
+
+ switch (vType)
+ {
+ case ::qpid::types::VAR_BOOL:
+ dict[elementName] = variant.asBool();
+ break;
+
+ case ::qpid::types::VAR_UINT8:
+ dict[elementName] = variant.asUint8();
+ break;
+
+ case ::qpid::types::VAR_UINT16:
+ dict[elementName] = variant.asUint16();
+ break;
+
+ case ::qpid::types::VAR_UINT32:
+ dict[elementName] = variant.asUint32();
+ break;
+
+ case ::qpid::types::VAR_UINT64:
+ dict[elementName] = variant.asUint64();
+ break;
+
+ case ::qpid::types::VAR_INT8:
+ dict[elementName] = variant.asInt8();
+ break;
+
+ case ::qpid::types::VAR_INT16:
+ dict[elementName] = variant.asInt16();
+ break;
+
+ case ::qpid::types::VAR_INT32:
+ dict[elementName] = variant.asInt32();
+ break;
+
+ case ::qpid::types::VAR_INT64:
+ dict[elementName] = variant.asInt64();
+ break;
+
+ case ::qpid::types::VAR_FLOAT:
+ dict[elementName] = variant.asFloat();
+ break;
+
+ case ::qpid::types::VAR_DOUBLE:
+ dict[elementName] = variant.asDouble();
+ break;
+
+ case ::qpid::types::VAR_STRING:
+ {
+ System::String ^ elementValue = gcnew System::String(variant.asString().c_str());
+ dict[elementName] = elementValue;
+ break;
+ }
+ case ::qpid::types::VAR_MAP:
+ {
+ VMap ^ newDict = gcnew VMap();
+
+ Decode (newDict, variant.asMap());
+
+ dict[elementName] = newDict;
+ break;
+ }
+
+ case ::qpid::types::VAR_LIST:
+ {
+ VList ^ newList = gcnew VList();
+
+ Decode (newList, variant.asList());
+
+ dict[elementName] = newList;
+ break;
+ }
+
+ case ::qpid::types::VAR_UUID:
+ break;
+ }
+ }
+ }
+
+
+ //
+ // User wants to extract a list from the message
+ //
+ void Message::getContent(System::Collections::Generic::List<
+ System::Object^> ^ list)
+ {
+ // Extract the message map from the message
+ ::qpid::types::Variant::List vList;
+
+ ::qpid::messaging::decode(*messagep, vList, QpidMarshal::ToNative("amqp/list"));
+
+ Decode(list, vList);
+ }
+
+
+ void Message::Decode(VList ^ vList, ::qpid::types::Variant::List & qpidList)
+ {
+ // For each object in the message map,
+ // create a .NET object and add it to the dictionary.
+ for (::qpid::types::Variant::List::const_iterator i = qpidList.begin(); i != qpidList.end(); ++i)
+ {
+ ::qpid::types::Variant variant = *i;
+ ::qpid::types::VariantType vType = variant.getType();
+
+ switch (vType)
+ {
+ case ::qpid::types::VAR_BOOL:
+ (*vList).Add(variant.asBool());
+ break;
+
+ case ::qpid::types::VAR_UINT8:
+ (*vList).Add(variant.asUint8());
+ break;
+
+ case ::qpid::types::VAR_UINT16:
+ (*vList).Add(variant.asUint16());
+ break;
+
+ case ::qpid::types::VAR_UINT32:
+ (*vList).Add(variant.asUint32());
+ break;
+
+ case ::qpid::types::VAR_UINT64:
+ (*vList).Add(variant.asUint64());
+ break;
+
+ case ::qpid::types::VAR_INT8:
+ (*vList).Add(variant.asInt8());
+ break;
+
+ case ::qpid::types::VAR_INT16:
+ (*vList).Add(variant.asInt16());
+ break;
+
+ case ::qpid::types::VAR_INT32:
+ (*vList).Add(variant.asInt32());
+ break;
+
+ case ::qpid::types::VAR_INT64:
+ (*vList).Add(variant.asInt64());
+ break;
+
+ case ::qpid::types::VAR_FLOAT:
+ (*vList).Add(variant.asFloat());
+ break;
+
+ case ::qpid::types::VAR_DOUBLE:
+ (*vList).Add(variant.asDouble());
+ break;
+
+ case ::qpid::types::VAR_STRING:
+ {
+ System::String ^ elementValue = gcnew System::String(variant.asString().c_str());
+ (*vList).Add(elementValue);
+ break;
+ }
+ case ::qpid::types::VAR_MAP:
+ {
+ VMap ^ newDict = gcnew VMap();
+
+ Decode (newDict, variant.asMap());
+
+ (*vList).Add(newDict);
+ break;
+ }
+
+ case ::qpid::types::VAR_LIST:
+ {
+ VList ^ newList = gcnew VList();
+
+ Decode (newList, variant.asList());
+
+ (*vList).Add(newList);
+ break;
+ }
+
+ case ::qpid::types::VAR_UUID:
+ break;
+ }
+ }
+ }
}}}}
diff --git a/cpp/bindings/qpid/dotnet/src/Message.h b/cpp/bindings/qpid/dotnet/src/Message.h
index 2219112d3f..c308fdf29f 100644
--- a/cpp/bindings/qpid/dotnet/src/Message.h
+++ b/cpp/bindings/qpid/dotnet/src/Message.h
@@ -31,11 +31,19 @@ namespace apache {
namespace qpid {
namespace messaging {
+typedef System::Collections::Generic::Dictionary<
+ System::String^,
+ System::Object^>
+ VMap;
+
+typedef System::Collections::Generic::List<
+ System::Object^>
+ VList;
+
/// <summary>
/// Message is a managed wrapper for a ::qpid::messaging::Message
/// </summary>
-
public ref class Message
{
@@ -43,11 +51,57 @@ namespace messaging {
// Kept object deletion code
void Cleanup();
+ bool objIsMap (System::Object ^ op)
+ {
+ return (*op).GetType() == pVMapType;
+ }
+
+ bool objIsList(System::Object ^ op)
+ {
+ return (*op).GetType() == pVListType;
+ }
+
+ // The given object is a Dictionary.
+ // Add its elements to the qpid map.
+ void Encode(::qpid::types::Variant::Map & theMapp,
+ VMap ^ theObjp);
+
+ // The given object is a List.
+ // Add its elements to the qpid list.
+ void Encode(::qpid::types::Variant::List & theListp,
+ VList ^ theObjp);
+
+ // Returns a variant representing simple native type object.
+ // Not to be called for Map/List objects.
+ void EncodeObject(System::Object ^ theObjp,
+ ::qpid::types::Variant & targetp);
+
+
+ void Decode(VMap ^ dict, ::qpid::types::Variant::Map & map);
+
+ void Decode(VList ^ vList, ::qpid::types::Variant::List & qpidList);
+
+
+ // map and list for type comparison
+ VMap aVMap;
+ VList aVList;
+ System::Type ^ pVMapType;
+ System::Type ^ pVListType;
+
public:
+ // Create from String
Message(System::String ^ bytes);
+
+ // Create from object
+ Message(System::Object ^ obj);
+
+ // Create reference copy
Message(::qpid::messaging::Message * msgp);
+
~Message();
!Message();
+
+ // Copy constructor
Message(const Message % rhs);
// The kept object in the Messaging C++ DLL
@@ -88,5 +142,12 @@ namespace messaging {
void setContent(System::String ^ content);
System::String ^ getContent();
+
+ void getContent(System::Collections::Generic::Dictionary<
+ System::String^,
+ System::Object^> ^ dict);
+
+ void getContent(System::Collections::Generic::List<
+ System::Object^> ^);
};
}}}}