summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/broker/Selector.cpp
diff options
context:
space:
mode:
authorAndrew Stitcher <astitcher@apache.org>2013-03-04 21:08:45 +0000
committerAndrew Stitcher <astitcher@apache.org>2013-03-04 21:08:45 +0000
commitdfada942aa6795a44bcf6988fc300d0767c994e8 (patch)
tree07e59fa97f4a2d3a83e1e5a06786101251439497 /cpp/src/qpid/broker/Selector.cpp
parent5ebf2fd5b0e7ada7089437efa95e37c6f473fcfc (diff)
downloadqpid-python-dfada942aa6795a44bcf6988fc300d0767c994e8.tar.gz
QPID-4558: Selectors for C++ broker
- Added numeric and boolean values * To literals and identifier values * To the code that extracts values from message properties - Added the full set of comparison operators - Implemented full "unknown" semantics for all operators. - Implemented extended "is null" and "is not null" operators that allow expressions as well as just identifiers. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1452525 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/broker/Selector.cpp')
-rw-r--r--cpp/src/qpid/broker/Selector.cpp165
1 files changed, 104 insertions, 61 deletions
diff --git a/cpp/src/qpid/broker/Selector.cpp b/cpp/src/qpid/broker/Selector.cpp
index 0880285692..62d2c43005 100644
--- a/cpp/src/qpid/broker/Selector.cpp
+++ b/cpp/src/qpid/broker/Selector.cpp
@@ -23,56 +23,23 @@
#include "qpid/broker/Message.h"
#include "qpid/broker/SelectorExpression.h"
+#include "qpid/broker/SelectorValue.h"
#include "qpid/log/Statement.h"
+#include "qpid/types/Variant.h"
#include <string>
#include <sstream>
+#include "qpid/sys/unordered_map.h"
#include <boost/make_shared.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
namespace qpid {
namespace broker {
using std::string;
-
-Selector::Selector(const string& e) :
- parse(parseTopBoolExpression(e)),
- expression(e)
-{
- bool debugOut;
- QPID_LOG_TEST(debug, debugOut);
- if (debugOut) {
- std::stringstream ss;
- parse->repr(ss);
- QPID_LOG(debug, "Selector parsed[" << e << "] into: " << ss.str());
- }
-}
-
-Selector::~Selector()
-{
-}
-
-bool Selector::eval(const SelectorEnv& env)
-{
- return parse->eval(env);
-}
-
-bool Selector::filter(const Message& msg)
-{
- return eval(MessageSelectorEnv(msg));
-}
-
-MessageSelectorEnv::MessageSelectorEnv(const Message& m) :
- msg(m)
-{
-}
-
-bool MessageSelectorEnv::present(const string& identifier) const
-{
- // If the value we get is void then most likely the property wasn't present
- return !msg.getProperty(identifier).isVoid();
-}
+using qpid::sys::unordered_map;
/**
* Identifier (amqp.) | JMS... | amqp 1.0 equivalent
@@ -89,48 +56,124 @@ bool MessageSelectorEnv::present(const string& identifier) const
* creation_time | Timestamp | creation-time properties section
* jms_type | Type | jms-type message-annotations section
*/
+const string EMPTY;
+const string PERSISTENT("PERSISTENT");
+const string NON_PERSISTENT("NON_PERSISTENT");
-string specialValue(const Message& msg, const string& id)
+const Value specialValue(const Message& msg, const string& id)
{
// TODO: Just use a simple if chain for now - improve this later
if ( id=="delivery_mode" ) {
- return msg.getEncoding().isPersistent() ? "PERSISTENT" : "NON_PERSISTENT";
+ return msg.getEncoding().isPersistent() ? PERSISTENT : NON_PERSISTENT;
} else if ( id=="redelivered" ) {
- return msg.getDeliveryCount()>0 ? "TRUE" : "FALSE";
+ return msg.getDeliveryCount()>0 ? true : false;
} else if ( id=="priority" ) {
- return boost::lexical_cast<string>(static_cast<uint32_t>(msg.getEncoding().getPriority()));
+ return int64_t(msg.getPriority());
} else if ( id=="correlation_id" ) {
- return ""; // Needs an indirection in getEncoding().
+ return EMPTY; // Needs an indirection in getEncoding().
} else if ( id=="message_id" ) {
- return ""; // Needs an indirection in getEncoding().
+ return EMPTY; // Needs an indirection in getEncoding().
} else if ( id=="to" ) {
- return msg.getRoutingKey(); // This is good for 0-10, not sure about 1.0
+ return EMPTY; // This is good for 0-10, not sure about 1.0
} else if ( id=="reply_to" ) {
- return ""; // Needs an indirection in getEncoding().
+ return EMPTY; // Needs an indirection in getEncoding().
} else if ( id=="absolute_expiry_time" ) {
- return ""; // Needs an indirection in getEncoding().
+ return EMPTY; // Needs an indirection in getEncoding().
} else if ( id=="creation_time" ) {
- return ""; // Needs an indirection in getEncoding().
+ return EMPTY; // Needs an indirection in getEncoding().
} else if ( id=="jms_type" ) {
- return msg.getAnnotation("jms-type");
- } else return "";
+ return EMPTY;
+ } else return Value();
}
-string MessageSelectorEnv::value(const string& identifier) const
+class MessageSelectorEnv : public SelectorEnv {
+ const Message& msg;
+ mutable boost::ptr_vector<string> returnedStrings;
+ mutable unordered_map<string, Value> returnedValues;
+
+ const Value& value(const string&) const;
+
+public:
+ MessageSelectorEnv(const Message&);
+};
+
+MessageSelectorEnv::MessageSelectorEnv(const Message& m) :
+msg(m)
+{
+}
+
+const Value& MessageSelectorEnv::value(const string& identifier) const
+{
+ if (returnedValues.find(identifier)==returnedValues.end()) {
+ Value v;
+
+ // Check for amqp prefix and strip it if present
+ if (identifier.substr(0, 5) == "amqp.") {
+ v = specialValue(msg, identifier.substr(5));
+ } else {
+ // Just return property as string
+ //v = &msg.getPropertyAsString(identifier);
+ qpid::types::Variant var = msg.getProperty(identifier);
+ switch (var.getType()) {
+ case types::VAR_VOID:
+ v = Value(); break;
+ case types::VAR_STRING: {
+ string& s = var.getString();
+ returnedStrings.push_back(new string(s));
+ v = returnedStrings[returnedStrings.size()-1];
+ break;
+ }
+ case types::VAR_UINT64:
+ // TODO: Need to take care of values too high to be int64_t
+ case types::VAR_UINT32:
+ case types::VAR_UINT16:
+ case types::VAR_UINT8:
+ case types::VAR_INT64:
+ case types::VAR_INT32:
+ case types::VAR_INT16:
+ case types::VAR_INT8:
+ v = var.asInt64(); break;
+ case types::VAR_FLOAT:
+ case types::VAR_DOUBLE:
+ v = var.asDouble(); break;
+ case types::VAR_BOOL:
+ v = var.asBool(); break;
+ default:
+ v = Value(); break;
+ }
+ }
+ QPID_LOG(debug, "Selector identifier: " << identifier << "->" << v);
+ returnedValues[identifier] = v;
+ }
+ return returnedValues[identifier];
+}
+
+Selector::Selector(const string& e) :
+ parse(TopExpression::parse(e)),
+ expression(e)
{
- string v;
-
- // Check for amqp prefix and strip it if present
- if (identifier.substr(0, 5) == "amqp.") {
- v = specialValue(msg, identifier.substr(5));
- } else {
- // Just return property as string
- v = msg.getPropertyAsString(identifier);
+ bool debugOut;
+ QPID_LOG_TEST(debug, debugOut);
+ if (debugOut) {
+ std::stringstream ss;
+ parse->repr(ss);
+ QPID_LOG(debug, "Selector parsed[" << e << "] into: " << ss.str());
}
- QPID_LOG(debug, "Selector identifier: " << identifier << "->" << v);
- return v;
}
+Selector::~Selector()
+{
+}
+
+bool Selector::eval(const SelectorEnv& env)
+{
+ return parse->eval(env);
+}
+
+bool Selector::filter(const Message& msg)
+{
+ return eval(MessageSelectorEnv(msg));
+}
namespace {
const boost::shared_ptr<Selector> NULL_SELECTOR = boost::shared_ptr<Selector>();