You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by tr...@apache.org on 2009/05/22 23:40:58 UTC

svn commit: r777720 [2/2] - in /qpid/trunk/qpid/cpp/src: ./ qmf/

Added: qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.cpp?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.cpp (added)
+++ qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.cpp Fri May 22 21:40:57 2009
@@ -0,0 +1,460 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "ResilientConnection.h"
+#include "MessageImpl.h"
+#include <qpid/client/Session.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+#include <qpid/client/Message.h>
+#include <qpid/sys/Thread.h>
+#include <qpid/sys/Runnable.h>
+#include <qpid/sys/Mutex.h>
+#include <qpid/sys/Condition.h>
+#include <qpid/log/Statement.h>
+#include <qpid/RefCounted.h>
+#include <boost/bind.hpp>
+#include <string>
+#include <deque>
+#include <vector>
+#include <set>
+#include <boost/intrusive_ptr.hpp>
+
+using namespace std;
+using namespace qmf;
+using namespace qpid::client;
+using qpid::sys::Mutex;
+
+namespace qmf {
+    struct ResilientConnectionEventImpl {
+        ResilientConnectionEvent::EventKind  kind;
+        void*       sessionContext;
+        string      errorText;
+        MessageImpl message;
+
+        ResilientConnectionEventImpl(ResilientConnectionEvent::EventKind k,
+                                     const MessageImpl& m = MessageImpl()) :
+            kind(k), sessionContext(0), message(m) {}
+        ResilientConnectionEvent copy();
+    };
+
+    struct RCSession : public MessageListener, public qpid::sys::Runnable, public qpid::RefCounted {
+        typedef boost::intrusive_ptr<RCSession> Ptr;
+        ResilientConnectionImpl& connImpl;
+        string name;
+        Connection& connection;
+        Session session;
+        SubscriptionManager* subscriptions;
+        void* userContext;
+        vector<string> dests;
+        qpid::sys::Thread thread;
+
+        RCSession(ResilientConnectionImpl& ci, const string& n, Connection& c, void* uc) :
+            connImpl(ci), name(n), connection(c), session(connection.newSession(name)),
+            subscriptions(new SubscriptionManager(session)), userContext(uc), thread(*this) {}
+        ~RCSession();
+        void received(qpid::client::Message& msg);
+        void run();
+        void stop();
+    };
+
+    class ResilientConnectionImpl : public qpid::sys::Runnable {
+    public:
+        ResilientConnectionImpl(ConnectionSettings& settings,
+                                int dmin, int dmax, int dfactor);
+        ~ResilientConnectionImpl();
+
+        bool isConnected() const;
+        bool getEvent(ResilientConnectionEvent& event);
+        void popEvent();
+        bool createSession(const char* name, void* sessionContext, SessionHandle& handle);
+        void destroySession(SessionHandle handle);
+        void sendMessage(SessionHandle handle, qmf::Message& message);
+        void declareQueue(SessionHandle handle, char* queue);
+        void deleteQueue(SessionHandle handle, char* queue);
+        void bind(SessionHandle handle, char* exchange, char* queue, char* key);
+        void unbind(SessionHandle handle, char* exchange, char* queue, char* key);
+        void setNotifyFd(int fd);
+
+        void run();
+        void failure();
+        void sessionClosed(RCSession* sess);
+
+        void EnqueueEvent(ResilientConnectionEvent::EventKind kind,
+                          void*              sessionContext = 0,
+                          const MessageImpl& message = MessageImpl(),
+                          const string&      errorText = "");
+
+    private:
+        int  notifyFd;
+        bool connected;
+        bool shutdown;
+        string lastError;
+        ConnectionSettings settings;
+        Connection connection;
+        mutable qpid::sys::Mutex lock;
+        int delayMin;
+        int delayMax;
+        int delayFactor;
+        qpid::sys::Condition cond;
+        qpid::sys::Thread connThread;
+        deque<ResilientConnectionEventImpl> eventQueue;
+        set<RCSession::Ptr> sessions;
+    };
+}
+
+ResilientConnectionEvent ResilientConnectionEventImpl::copy()
+{
+    ResilientConnectionEvent item;
+
+    ::memset(&item, 0, sizeof(ResilientConnectionEvent));
+    item.kind = kind;
+    item.sessionContext = sessionContext;
+    item.message        = message.copy();
+    item.errorText      = const_cast<char*>(errorText.c_str());
+
+    return item;
+}
+
+RCSession::~RCSession()
+{
+    subscriptions->stop();
+    thread.join();
+    session.close();
+    delete subscriptions;
+}
+
+void RCSession::run()
+{
+    try {
+        subscriptions->run();
+    } catch (exception& e) {
+        connImpl.sessionClosed(this);
+    }
+}
+
+void RCSession::stop()
+{
+    subscriptions->stop();
+}
+
+void RCSession::received(qpid::client::Message& msg)
+{
+    qmf::MessageImpl qmsg;
+    qmsg.body = msg.getData();
+
+    qpid::framing::MessageProperties p = msg.getMessageProperties();
+    if (p.hasReplyTo()) {
+        const qpid::framing::ReplyTo& rt = p.getReplyTo();
+        qmsg.replyExchange = rt.getExchange();
+        qmsg.replyKey = rt.getRoutingKey();
+    }
+
+    if (p.hasUserId()) {
+        qmsg.userId = p.getUserId();
+    }
+
+    connImpl.EnqueueEvent(ResilientConnectionEvent::RECV, userContext, qmsg);
+}
+
+ResilientConnectionImpl::ResilientConnectionImpl(ConnectionSettings& _settings,
+                                                 int dmin, int dmax, int dfactor) :
+    notifyFd(-1), connected(false), shutdown(false), settings(_settings), 
+    delayMin(dmin), delayMax(dmax), delayFactor(dfactor), connThread(*this)
+{
+    connection.registerFailureCallback(boost::bind(&ResilientConnectionImpl::failure, this));
+}
+
+ResilientConnectionImpl::~ResilientConnectionImpl()
+{
+    shutdown = true;
+    connected = false;
+    cond.notify();
+    connThread.join();
+    connection.close();
+}
+
+bool ResilientConnectionImpl::isConnected() const
+{
+    Mutex::ScopedLock _lock(lock);
+    return connected;
+}
+
+bool ResilientConnectionImpl::getEvent(ResilientConnectionEvent& event)
+{
+    Mutex::ScopedLock _lock(lock);
+    if (eventQueue.empty())
+        return false;
+    event = eventQueue.front().copy();
+    return true;
+}
+
+void ResilientConnectionImpl::popEvent()
+{
+    Mutex::ScopedLock _lock(lock);
+    if (!eventQueue.empty())
+        eventQueue.pop_front();
+}
+
+bool ResilientConnectionImpl::createSession(const char* name, void* sessionContext,
+                                            SessionHandle& handle)
+{
+    Mutex::ScopedLock _lock(lock);
+    if (!connected)
+        return false;
+
+    RCSession::Ptr sess = RCSession::Ptr(new RCSession(*this, name, connection, sessionContext));
+
+    handle.handle = (void*) sess.get();
+    sessions.insert(sess);
+
+    return true;
+}
+
+void ResilientConnectionImpl::destroySession(SessionHandle handle)
+{
+    Mutex::ScopedLock _lock(lock);
+    RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.handle);
+    set<RCSession::Ptr>::iterator iter = sessions.find(sess);
+    if (iter != sessions.end()) {
+        for (vector<string>::iterator dIter = sess->dests.begin(); dIter != sess->dests.end(); dIter++)
+            sess->subscriptions->cancel(dIter->c_str());
+        sess->subscriptions->stop();
+        sess->subscriptions->wait();
+
+        sessions.erase(iter);
+        return;
+    }
+}
+
+void ResilientConnectionImpl::sendMessage(SessionHandle handle, qmf::Message& message)
+{
+    Mutex::ScopedLock _lock(lock);
+    RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.handle);
+    set<RCSession::Ptr>::iterator iter = sessions.find(sess);
+    qpid::client::Message msg;
+    string data(message.body, message.length);
+    msg.getDeliveryProperties().setRoutingKey(message.routingKey);
+    msg.getMessageProperties().setReplyTo(qpid::framing::ReplyTo(message.replyExchange, message.replyKey));
+    msg.setData(data);
+
+    try {
+        sess->session.messageTransfer(arg::content=msg, arg::destination=message.destination);
+    } catch(exception& e) {
+        QPID_LOG(error, "Session Exception during message-transfer: " << e.what());
+        sessions.erase(iter);
+        EnqueueEvent(ResilientConnectionEvent::SESSION_CLOSED, (*iter)->userContext);
+    }
+}
+
+void ResilientConnectionImpl::declareQueue(SessionHandle handle, char* queue)
+{
+    Mutex::ScopedLock _lock(lock);
+    RCSession* sess = (RCSession*) handle.handle;
+
+    sess->session.queueDeclare(arg::queue=queue, arg::autoDelete=true, arg::exclusive=true);
+    sess->subscriptions->subscribe(*sess, queue, queue);
+    sess->dests.push_back(string(queue));
+}
+
+void ResilientConnectionImpl::deleteQueue(SessionHandle handle, char* queue)
+{
+    Mutex::ScopedLock _lock(lock);
+    RCSession* sess = (RCSession*) handle.handle;
+
+    sess->session.queueDelete(arg::queue=queue);
+    for (vector<string>::iterator iter = sess->dests.begin();
+         iter != sess->dests.end(); iter++)
+        if (*iter == queue) {
+            sess->subscriptions->cancel(queue);
+            sess->dests.erase(iter);
+            break;
+        }
+}
+
+void ResilientConnectionImpl::bind(SessionHandle handle,
+                                   char* exchange, char* queue, char* key)
+{
+    Mutex::ScopedLock _lock(lock);
+    RCSession* sess = (RCSession*) handle.handle;
+
+    sess->session.exchangeBind(arg::exchange=exchange, arg::queue=queue, arg::bindingKey=key);
+}
+
+void ResilientConnectionImpl::unbind(SessionHandle handle,
+                                     char* exchange, char* queue, char* key)
+{
+    Mutex::ScopedLock _lock(lock);
+    RCSession* sess = (RCSession*) handle.handle;
+
+    sess->session.exchangeUnbind(arg::exchange=exchange, arg::queue=queue, arg::bindingKey=key);
+}
+
+void ResilientConnectionImpl::setNotifyFd(int fd)
+{
+    notifyFd = fd;
+}
+
+void ResilientConnectionImpl::run()
+{
+    int delay(delayMin);
+
+    while (true) {
+        try {
+            connection.open(settings);
+            {
+                Mutex::ScopedLock _lock(lock);
+                connected = true;
+                EnqueueEvent(ResilientConnectionEvent::CONNECTED);
+
+                while (connected)
+                    cond.wait(lock);
+
+                while (!sessions.empty()) {
+                    set<RCSession::Ptr>::iterator iter = sessions.begin();
+                    RCSession::Ptr sess = *iter;
+                    sessions.erase(iter);
+                    EnqueueEvent(ResilientConnectionEvent::SESSION_CLOSED, sess->userContext);
+                    Mutex::ScopedUnlock _u(lock);
+                    sess->stop();
+                }
+
+                EnqueueEvent(ResilientConnectionEvent::DISCONNECTED);
+
+                if (shutdown)
+                    return;
+            }
+            delay = delayMin;
+            connection.close();
+        } catch (exception &e) {
+            QPID_LOG(debug, "connection.open exception: " << e.what());
+            Mutex::ScopedLock _lock(lock);
+            lastError = e.what();
+            if (delay < delayMax)
+                delay *= delayFactor;
+        }
+
+        ::sleep(delay);
+    }
+}
+
+void ResilientConnectionImpl::failure()
+{
+    Mutex::ScopedLock _lock(lock);
+
+    connected = false;
+    lastError = "Closed by Peer";
+    cond.notify();
+}
+
+void ResilientConnectionImpl::sessionClosed(RCSession*)
+{
+    Mutex::ScopedLock _lock(lock);
+    connected = false;
+    lastError = "Closed due to Session failure";
+    cond.notify();
+}
+
+void ResilientConnectionImpl::EnqueueEvent(ResilientConnectionEvent::EventKind kind,
+                                           void* sessionContext,
+                                           const MessageImpl& message,
+                                           const string& errorText)
+{
+    Mutex::ScopedLock _lock(lock);
+    ResilientConnectionEventImpl event(kind, message);
+
+    event.sessionContext = sessionContext;
+    event.errorText      = errorText;
+
+    eventQueue.push_back(event);
+    if (notifyFd != -1)
+        ::write(notifyFd, ".", 1);
+}
+
+
+//==================================================================
+// Wrappers
+//==================================================================
+
+ResilientConnection::ResilientConnection(ConnectionSettings& settings,
+                                         int delayMin, int delayMax, int delayFactor)
+{
+    impl = new ResilientConnectionImpl(settings, delayMin, delayMax, delayFactor);
+}
+
+ResilientConnection::~ResilientConnection()
+{
+    delete impl;
+}
+
+bool ResilientConnection::isConnected() const
+{
+    return impl->isConnected();
+}
+
+bool ResilientConnection::getEvent(ResilientConnectionEvent& event)
+{
+    return impl->getEvent(event);
+}
+
+void ResilientConnection::popEvent()
+{
+    impl->popEvent();
+}
+
+bool ResilientConnection::createSession(const char* name, void* sessionContext, SessionHandle& handle)
+{
+    return impl->createSession(name, sessionContext, handle);
+}
+
+void ResilientConnection::destroySession(SessionHandle handle)
+{
+    impl->destroySession(handle);
+}
+
+void ResilientConnection::sendMessage(SessionHandle handle, qmf::Message& message)
+{
+    impl->sendMessage(handle, message);
+}
+
+void ResilientConnection::declareQueue(SessionHandle handle, char* queue)
+{
+    impl->declareQueue(handle, queue);
+}
+
+void ResilientConnection::deleteQueue(SessionHandle handle, char* queue)
+{
+    impl->deleteQueue(handle, queue);
+}
+
+void ResilientConnection::bind(SessionHandle handle, char* exchange, char* queue, char* key)
+{
+    impl->bind(handle, exchange, queue, key);
+}
+
+void ResilientConnection::unbind(SessionHandle handle, char* exchange, char* queue, char* key)
+{
+    impl->unbind(handle, exchange, queue, key);
+}
+
+void ResilientConnection::setNotifyFd(int fd)
+{
+    impl->setNotifyFd(fd);
+}
+

Added: qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.h?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.h (added)
+++ qpid/trunk/qpid/cpp/src/qmf/ResilientConnection.h Fri May 22 21:40:57 2009
@@ -0,0 +1,166 @@
+#ifndef _QmfResilientConnection_
+#define _QmfResilientConnection_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <qmf/Message.h>
+#include <qpid/client/Connection.h>
+#include <qpid/client/ConnectionSettings.h>
+#include <string>
+
+namespace qmf {
+
+    /**
+     * Represents events that occur, unsolicited, from ResilientConnection.
+     */
+    struct ResilientConnectionEvent {
+        enum EventKind {
+            CONNECTED      = 1,
+            DISCONNECTED   = 2,
+            SESSION_CLOSED = 3,
+            RECV           = 4
+        };
+
+        EventKind kind;
+        void*     sessionContext; // SESSION_CLOSED, RECV
+        char*     errorText;      // DISCONNECTED, SESSION_CLOSED
+        Message   message;        // RECV
+    };
+
+    struct SessionHandle {
+        void* handle;
+    };
+
+    class ResilientConnectionImpl;
+
+    /**
+     * ResilientConnection represents a Qpid connection that is resilient.
+     *
+     * Upon creation, ResilientConnection attempts to establish a connection to the
+     * messaging broker.  If it fails, it will continue to retry at an interval that
+     * increases over time (to a maximum interval).  If an extablished connection is
+     * dropped, a reconnect will be attempted.
+     */
+    class ResilientConnection {
+    public:
+
+        /**
+         * Create a new resilient connection.
+         *@param settings Settings that define how the connection is to be made.
+         *@param delayMin Minimum delay (in seconds) between retries.
+         *@param delayMax Maximum delay (in seconds) between retries.
+         *@param delayFactor Factor to multiply retry delay by after each failure.
+         */
+        ResilientConnection(qpid::client::ConnectionSettings& settings,
+                            int delayMin = 1,
+                            int delayMax = 128,
+                            int delayFactor = 2);
+        ~ResilientConnection();
+
+        /**
+         * Get the connected status of the resilient connection.
+         *@return true iff the connection is established.
+         */
+        bool isConnected() const;
+
+        /**
+         * Get the next event (if present) from the connection.
+         *@param event Returned event if one is available.
+         *@return true if event is valid, false if there are no more events to handle.
+         */
+        bool getEvent(ResilientConnectionEvent& event);
+
+        /**
+         * Discard the event on the front of the queue.  This should be invoked after processing
+         * the event from getEvent.
+         */
+        void popEvent();
+
+        /**
+         * Create a new AMQP session.
+         *@param name Unique name for the session.
+         *@param sessionContext Optional user-context value that will be provided in events
+         *                      pertaining to this session.
+         *@param handle Output handle to be stored and used in subsequent calls pertaining to
+         *              this session.
+         *@return true iff the session was successfully created.
+         */
+        bool createSession(const char* name, void* sessionContext, SessionHandle& handle);
+
+        /**
+         * Destroy a created session.
+         *@param handle SessionHandle returned by createSession.
+         */
+        void destroySession(SessionHandle handle);
+
+        /**
+         * Send a message into the AMQP broker via a session.
+         *@param handle The session handle of the session to transmit through.
+         *@param message The QMF message to transmit.
+         */
+        void sendMessage(SessionHandle handle, Message& message);
+
+        /**
+         * Declare an exclusive, auto-delete queue for a session.
+         *@param handle The session handle for the owner of the queue.
+         *@param queue The name of the queue.
+         */
+        void declareQueue(SessionHandle handle, char* queue);
+
+        /**
+         * Delete a queue.
+         *@param handle The session handle for the owner of the queue.
+         *@param queue The name of the queue.
+         */
+        void deleteQueue(SessionHandle handle, char* queue);
+
+        /**
+         * Bind a queue to an exchange.
+         *@param handle The session handle of the session to use for binding.
+         *@param exchange The name of the exchange for binding.
+         *@param queue The name of the queue for binding.
+         *@param key The binding key.
+         */
+        void bind(SessionHandle handle, char* exchange, char* queue, char* key);
+
+        /**
+         * Remove a binding.
+         *@param handle The session handle of the session to use for un-binding.
+         *@param exchange The name of the exchange.
+         *@param queue The name of the queue.
+         *@param key The binding key.
+         */
+        void unbind(SessionHandle handle, char* exchange, char* queue, char* key);
+
+        /**
+         * Establish a file descriptor for event notification.
+         *@param fd A file descriptor into which the connection shall write a character each
+         *          time an event is enqueued.  This fd may be in a pair, the other fd of which
+         *          is used in a select loop to control execution.
+         */
+        void setNotifyFd(int fd);
+
+    private:
+        ResilientConnectionImpl* impl;
+    };
+}
+
+#endif
+

Added: qpid/trunk/qpid/cpp/src/qmf/Schema.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/Schema.h?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/Schema.h (added)
+++ qpid/trunk/qpid/cpp/src/qmf/Schema.h Fri May 22 21:40:57 2009
@@ -0,0 +1,160 @@
+#ifndef _QmfSchema_
+#define _QmfSchema_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <qmf/Typecode.h>
+#include <stdint.h>
+
+namespace qmf {
+
+    enum Access { ACCESS_READ_CREATE = 1, ACCESS_READ_WRITE = 2, ACCESS_READ_ONLY = 3 };
+    enum Direction { DIR_IN = 1, DIR_OUT = 2, DIR_IN_OUT = 3 };
+    enum ClassKind { CLASS_OBJECT = 1, CLASS_EVENT = 2 };
+
+    class SchemaArgumentImpl;
+    class SchemaMethodImpl;
+    class SchemaPropertyImpl;
+    class SchemaStatisticImpl;
+    class SchemaObjectClassImpl;
+    class SchemaEventClassImpl;
+
+    /**
+     */
+    class SchemaArgument {
+    public:
+        SchemaArgument(const char* name, Typecode typecode);
+        SchemaArgument(SchemaArgumentImpl* impl);
+        ~SchemaArgument();
+        void setDirection(Direction dir);
+        void setUnit(const char* val);
+        void setDesc(const char* desc);
+        const char* getName() const;
+        Typecode getType() const;
+        Direction getDirection() const;
+        const char* getUnit() const;
+        const char* getDesc() const;
+
+        SchemaArgumentImpl* impl;
+    };
+
+    /**
+     */
+    class SchemaMethod {
+    public:
+        SchemaMethod(const char* name);
+        SchemaMethod(SchemaMethodImpl* impl);
+        ~SchemaMethod();
+        void addArgument(const SchemaArgument& argument);
+        void setDesc(const char* desc);
+        const char* getName() const;
+        const char* getDesc() const;
+        int getArgumentCount() const;
+        const SchemaArgument* getArgument(int idx) const;
+
+        SchemaMethodImpl* impl;
+    };
+
+    /**
+     */
+    class SchemaProperty {
+    public:
+        SchemaProperty(const char* name, Typecode typecode);
+        SchemaProperty(SchemaPropertyImpl* impl);
+        ~SchemaProperty();
+        void setAccess(Access access);
+        void setIndex(bool val);
+        void setOptional(bool val);
+        void setUnit(const char* val);
+        void setDesc(const char* desc);
+        const char* getName() const;
+        Typecode getType() const;
+        Access getAccess() const;
+        bool isIndex() const;
+        bool isOptional() const;
+        const char* getUnit() const;
+        const char* getDesc() const;
+
+        SchemaPropertyImpl* impl;
+    };
+
+    /**
+     */
+    class SchemaStatistic {
+    public:
+        SchemaStatistic(const char* name, Typecode typecode);
+        SchemaStatistic(SchemaStatisticImpl* impl);
+        ~SchemaStatistic();
+        void setUnit(const char* val);
+        void setDesc(const char* desc);
+        const char* getName() const;
+        Typecode getType() const;
+        const char* getUnit() const;
+        const char* getDesc() const;
+
+        SchemaStatisticImpl* impl;
+    };
+
+    /**
+     */
+    class SchemaObjectClass {
+    public:
+        SchemaObjectClass(const char* package, const char* name);
+        SchemaObjectClass(SchemaObjectClassImpl* impl);
+        ~SchemaObjectClass();
+        void addProperty(const SchemaProperty& property);
+        void addStatistic(const SchemaStatistic& statistic);
+        void addMethod(const SchemaMethod& method);
+
+        const char* getPackage() const;
+        const char* getName() const;
+        const uint8_t* getHash() const;
+        int getPropertyCount() const;
+        int getStatisticCount() const;
+        int getMethodCount() const;
+        const SchemaProperty* getProperty(int idx) const;
+        const SchemaStatistic* getStatistic(int idx) const;
+        const SchemaMethod* getMethod(int idx) const;
+
+        SchemaObjectClassImpl* impl;
+    };
+
+    /**
+     */
+    class SchemaEventClass {
+    public:
+        SchemaEventClass(const char* package, const char* name);
+        SchemaEventClass(SchemaEventClassImpl* impl);
+        ~SchemaEventClass();
+        void addArgument(const SchemaArgument& argument);
+        void setDesc(const char* desc);
+
+        const char* getPackage() const;
+        const char* getName() const;
+        const uint8_t* getHash() const;
+        int getArgumentCount() const;
+        const SchemaArgument* getArgument(int idx) const;
+
+        SchemaEventClassImpl* impl;
+    };
+}
+
+#endif
+

Added: qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.cpp?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.cpp (added)
+++ qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.cpp Fri May 22 21:40:57 2009
@@ -0,0 +1,740 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "SchemaImpl.h"
+#include <qpid/framing/Buffer.h>
+#include <qpid/framing/FieldTable.h>
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace qmf;
+using qpid::framing::Buffer;
+using qpid::framing::FieldTable;
+
+SchemaHash::SchemaHash()
+{
+    for (int idx = 0; idx < 16; idx++)
+        hash[idx] = 0x5A;
+}
+
+void SchemaHash::encode(Buffer& buffer)
+{
+    buffer.putBin128(hash);
+}
+
+void SchemaHash::decode(Buffer& buffer)
+{
+    buffer.getBin128(hash);
+}
+
+void SchemaHash::update(uint8_t data)
+{
+    update((char*) &data, 1);
+}
+
+void SchemaHash::update(const char* data, uint32_t len)
+{
+    uint64_t* first  = (uint64_t*) hash;
+    uint64_t* second = (uint64_t*) hash + 1;
+
+    for (uint32_t idx = 0; idx < len; idx++) {
+        *first = *first ^ (uint64_t) data[idx];
+        *second = *second << 1;
+        *second |= ((*first & 0x8000000000000000LL) >> 63);
+        *first = *first << 1;
+        *first = *first ^ *second;
+    }
+}
+
+SchemaArgumentImpl::SchemaArgumentImpl(Buffer& buffer) : envelope(new SchemaArgument(this))
+{
+    FieldTable map;
+    map.decode(buffer);
+
+    name = map.getAsString("name");
+    typecode = (Typecode) map.getAsInt("type");
+    unit = map.getAsString("unit");
+    description = map.getAsString("desc");
+
+    dir = DIR_IN;
+    string dstr(map.getAsString("dir"));
+    if (dstr == "O")
+        dir = DIR_OUT;
+    else if (dstr == "IO")
+        dir = DIR_IN_OUT;
+}
+
+void SchemaArgumentImpl::encode(Buffer& buffer) const
+{
+    FieldTable map;
+
+    map.setString("name", name);
+    map.setInt("type", (int) typecode);
+    if (dir == DIR_IN)
+        map.setString("dir", "I");
+    else if (dir == DIR_OUT)
+        map.setString("dir", "O");
+    else
+        map.setString("dir", "IO");
+    if (!unit.empty())
+        map.setString("unit", unit);
+    if (!description.empty())
+        map.setString("desc", description);
+
+    map.encode(buffer);
+}
+
+void SchemaArgumentImpl::updateHash(SchemaHash& hash) const
+{
+    hash.update(name);
+    hash.update(typecode);
+    hash.update(dir);
+    hash.update(unit);
+    hash.update(description);
+}
+
+SchemaMethodImpl::SchemaMethodImpl(Buffer& buffer) : envelope(new SchemaMethod(this))
+{
+    FieldTable map;
+    int argCount;
+
+    map.decode(buffer);
+    name = map.getAsString("name");
+    argCount = map.getAsInt("argCount");
+    description = map.getAsString("desc");
+
+    for (int idx = 0; idx < argCount; idx++) {
+        SchemaArgumentImpl* arg = new SchemaArgumentImpl(buffer);
+        addArgument(*arg->envelope);
+    }
+}
+
+void SchemaMethodImpl::encode(Buffer& buffer) const
+{
+    FieldTable map;
+
+    map.setString("name", name);
+    map.setInt("argCount", arguments.size());
+    if (!description.empty())
+        map.setString("desc", description);
+    map.encode(buffer);
+
+    for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+         iter != arguments.end(); iter++)
+        (*iter)->encode(buffer);
+}
+
+void SchemaMethodImpl::addArgument(const SchemaArgument& argument)
+{
+    arguments.push_back(argument.impl);
+}
+
+const SchemaArgument* SchemaMethodImpl::getArgument(int idx) const
+{
+    int count = 0;
+    for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+         iter != arguments.end(); iter++, count++)
+        if (idx == count)
+            return (*iter)->envelope;
+    return 0;
+}
+
+void SchemaMethodImpl::updateHash(SchemaHash& hash) const
+{
+    hash.update(name);
+    hash.update(description);
+    for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+         iter != arguments.end(); iter++)
+        (*iter)->updateHash(hash);
+}
+
+SchemaPropertyImpl::SchemaPropertyImpl(Buffer& buffer) : envelope(new SchemaProperty(this))
+{
+    FieldTable map;
+    map.decode(buffer);
+
+    name = map.getAsString("name");
+    typecode = (Typecode) map.getAsInt("type");
+    access = (Access) map.getAsInt("access");
+    index = map.getAsInt("index") != 0;
+    optional = map.getAsInt("optional") != 0;
+    unit = map.getAsString("unit");
+    description = map.getAsString("desc");
+}
+
+void SchemaPropertyImpl::encode(Buffer& buffer) const
+{
+    FieldTable map;
+
+    map.setString("name", name);
+    map.setInt("type", (int) typecode);
+    map.setInt("access", (int) access);
+    map.setInt("index", index ? 1 : 0);
+    map.setInt("optional", optional ? 1 : 0);
+    if (!unit.empty())
+        map.setString("unit", unit);
+    if (!description.empty())
+        map.setString("desc", description);
+
+    map.encode(buffer);
+}
+
+void SchemaPropertyImpl::updateHash(SchemaHash& hash) const
+{
+    hash.update(name);
+    hash.update(typecode);
+    hash.update(access);
+    hash.update(index);
+    hash.update(optional);
+    hash.update(unit);
+    hash.update(description);
+}
+
+SchemaStatisticImpl::SchemaStatisticImpl(Buffer& buffer) : envelope(new SchemaStatistic(this))
+{
+    FieldTable map;
+    map.decode(buffer);
+
+    name = map.getAsString("name");
+    typecode = (Typecode) map.getAsInt("type");
+    unit = map.getAsString("unit");
+    description = map.getAsString("desc");
+}
+
+void SchemaStatisticImpl::encode(Buffer& buffer) const
+{
+    FieldTable map;
+
+    map.setString("name", name);
+    map.setInt("type", (int) typecode);
+    if (!unit.empty())
+        map.setString("unit", unit);
+    if (!description.empty())
+        map.setString("desc", description);
+
+    map.encode(buffer);
+}
+
+void SchemaStatisticImpl::updateHash(SchemaHash& hash) const
+{
+    hash.update(name);
+    hash.update(typecode);
+    hash.update(unit);
+    hash.update(description);
+}
+
+SchemaObjectClassImpl::SchemaObjectClassImpl(Buffer& buffer) : envelope(new SchemaObjectClass(this)), hasHash(true)
+{
+    buffer.getShortString(package);
+    buffer.getShortString(name);
+    hash.decode(buffer);
+
+    uint16_t propCount   = buffer.getShort();
+    uint16_t statCount   = buffer.getShort();
+    uint16_t methodCount = buffer.getShort();
+
+    for (uint16_t idx = 0; idx < propCount; idx++) {
+        SchemaPropertyImpl* property = new SchemaPropertyImpl(buffer);
+        addProperty(*property->envelope);
+    }
+
+    for (uint16_t idx = 0; idx < statCount; idx++) {
+        SchemaStatisticImpl* statistic = new SchemaStatisticImpl(buffer);
+        addStatistic(*statistic->envelope);
+    }
+
+    for (uint16_t idx = 0; idx < methodCount; idx++) {
+        SchemaMethodImpl* method = new SchemaMethodImpl(buffer);
+        addMethod(*method->envelope);
+    }
+}
+
+void SchemaObjectClassImpl::encode(Buffer& buffer) const
+{
+    buffer.putOctet((uint8_t) CLASS_OBJECT);
+    buffer.putShortString(package);
+    buffer.putShortString(name);
+    hash.encode(buffer);
+    buffer.putShort((uint16_t) properties.size());
+    buffer.putShort((uint16_t) statistics.size());
+    buffer.putShort((uint16_t) methods.size());
+
+    for (vector<SchemaPropertyImpl*>::const_iterator iter = properties.begin();
+         iter != properties.end(); iter++)
+        (*iter)->encode(buffer);
+    for (vector<SchemaStatisticImpl*>::const_iterator iter = statistics.begin();
+         iter != statistics.end(); iter++)
+        (*iter)->encode(buffer);
+    for (vector<SchemaMethodImpl*>::const_iterator iter = methods.begin();
+         iter != methods.end(); iter++)
+        (*iter)->encode(buffer);
+}
+
+const uint8_t* SchemaObjectClassImpl::getHash() const
+{
+    if (!hasHash) {
+        hasHash = true;
+        hash.update(package);
+        hash.update(name);
+        for (vector<SchemaPropertyImpl*>::const_iterator iter = properties.begin();
+             iter != properties.end(); iter++)
+            (*iter)->updateHash(hash);
+        for (vector<SchemaStatisticImpl*>::const_iterator iter = statistics.begin();
+             iter != statistics.end(); iter++)
+            (*iter)->updateHash(hash);
+        for (vector<SchemaMethodImpl*>::const_iterator iter = methods.begin();
+             iter != methods.end(); iter++)
+            (*iter)->updateHash(hash);
+    }
+
+    return hash.get();
+}
+
+void SchemaObjectClassImpl::addProperty(const SchemaProperty& property)
+{
+    properties.push_back(property.impl);
+}
+
+void SchemaObjectClassImpl::addStatistic(const SchemaStatistic& statistic)
+{
+    statistics.push_back(statistic.impl);
+}
+
+void SchemaObjectClassImpl::addMethod(const SchemaMethod& method)
+{
+    methods.push_back(method.impl);
+}
+
+const SchemaProperty* SchemaObjectClassImpl::getProperty(int idx) const
+{
+    int count = 0;
+    for (vector<SchemaPropertyImpl*>::const_iterator iter = properties.begin();
+         iter != properties.end(); iter++, count++)
+        if (idx == count)
+            return (*iter)->envelope;
+    return 0;
+}
+
+const SchemaStatistic* SchemaObjectClassImpl::getStatistic(int idx) const
+{
+    int count = 0;
+    for (vector<SchemaStatisticImpl*>::const_iterator iter = statistics.begin();
+         iter != statistics.end(); iter++, count++)
+        if (idx == count)
+            return (*iter)->envelope;
+    return 0;
+}
+
+const SchemaMethod* SchemaObjectClassImpl::getMethod(int idx) const
+{
+    int count = 0;
+    for (vector<SchemaMethodImpl*>::const_iterator iter = methods.begin();
+         iter != methods.end(); iter++, count++)
+        if (idx == count)
+            return (*iter)->envelope;
+    return 0;
+}
+
+SchemaEventClassImpl::SchemaEventClassImpl(Buffer& buffer) : envelope(new SchemaEventClass(this)), hasHash(true)
+{
+    buffer.getShortString(package);
+    buffer.getShortString(name);
+    hash.decode(buffer);
+
+    uint16_t argCount   = buffer.getShort();
+
+    for (uint16_t idx = 0; idx < argCount; idx++) {
+        SchemaArgumentImpl* argument = new SchemaArgumentImpl(buffer);
+        addArgument(*argument->envelope);
+    }
+}
+
+void SchemaEventClassImpl::encode(Buffer& buffer) const
+{
+    buffer.putOctet((uint8_t) CLASS_EVENT);
+    buffer.putShortString(package);
+    buffer.putShortString(name);
+    hash.encode(buffer);
+    buffer.putShort((uint16_t) arguments.size());
+
+    for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+         iter != arguments.end(); iter++)
+        (*iter)->encode(buffer);
+}
+
+const uint8_t* SchemaEventClassImpl::getHash() const
+{
+    if (!hasHash) {
+        hasHash = true;
+        hash.update(package);
+        hash.update(name);
+        for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+             iter != arguments.end(); iter++)
+            (*iter)->updateHash(hash);
+    }
+    return hash.get();
+}
+
+void SchemaEventClassImpl::addArgument(const SchemaArgument& argument)
+{
+    arguments.push_back(argument.impl);
+}
+
+const SchemaArgument* SchemaEventClassImpl::getArgument(int idx) const
+{
+    int count = 0;
+    for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+         iter != arguments.end(); iter++, count++)
+        if (idx == count)
+            return (*iter)->envelope;
+    return 0;
+}
+
+//==================================================================
+// Wrappers
+//==================================================================
+
+SchemaArgument::SchemaArgument(const char* name, Typecode typecode)
+{
+    impl = new SchemaArgumentImpl(this, name, typecode);
+}
+
+SchemaArgument::SchemaArgument(SchemaArgumentImpl* i) : impl(i) {}
+
+SchemaArgument::~SchemaArgument()
+{
+    delete impl;
+}
+
+void SchemaArgument::setDirection(Direction dir)
+{
+    impl->setDirection(dir);
+}
+
+void SchemaArgument::setUnit(const char* val)
+{
+    impl->setUnit(val);
+}
+
+void SchemaArgument::setDesc(const char* desc)
+{
+    impl->setDesc(desc);
+}
+
+const char* SchemaArgument::getName() const
+{
+    return impl->getName().c_str();
+}
+
+Typecode SchemaArgument::getType() const
+{
+    return impl->getType();
+}
+
+Direction SchemaArgument::getDirection() const
+{
+    return impl->getDirection();
+}
+
+const char* SchemaArgument::getUnit() const
+{
+    return impl->getUnit().c_str();
+}
+
+const char* SchemaArgument::getDesc() const
+{
+    return impl->getDesc().c_str();
+}
+
+SchemaMethod::SchemaMethod(const char* name)
+{
+    impl = new SchemaMethodImpl(this, name);
+}
+
+SchemaMethod::SchemaMethod(SchemaMethodImpl* i) : impl(i) {}
+
+SchemaMethod::~SchemaMethod()
+{
+    delete impl;
+}
+
+void SchemaMethod::addArgument(const SchemaArgument& argument)
+{
+    impl->addArgument(argument);
+}
+
+void SchemaMethod::setDesc(const char* desc)
+{
+    impl->setDesc(desc);
+}
+
+const char* SchemaMethod::getName() const
+{
+    return impl->getName().c_str();
+}
+
+const char* SchemaMethod::getDesc() const
+{
+    return impl->getDesc().c_str();
+}
+
+int SchemaMethod::getArgumentCount() const
+{
+    return impl->getArgumentCount();
+}
+
+const SchemaArgument* SchemaMethod::getArgument(int idx) const
+{
+    return impl->getArgument(idx);
+}
+
+SchemaProperty::SchemaProperty(const char* name, Typecode typecode)
+{
+    impl = new SchemaPropertyImpl(this, name, typecode);
+}
+
+SchemaProperty::SchemaProperty(SchemaPropertyImpl* i) : impl(i) {}
+
+SchemaProperty::~SchemaProperty()
+{
+    delete impl;
+}
+
+void SchemaProperty::setAccess(Access access)
+{
+    impl->setAccess(access);
+}
+
+void SchemaProperty::setIndex(bool val)
+{
+    impl->setIndex(val);
+}
+
+void SchemaProperty::setOptional(bool val)
+{
+    impl->setOptional(val);
+}
+
+void SchemaProperty::setUnit(const char* val)
+{
+    impl->setUnit(val);
+}
+
+void SchemaProperty::setDesc(const char* desc)
+{
+    impl->setDesc(desc);
+}
+
+const char* SchemaProperty::getName() const
+{
+    return impl->getName().c_str();
+}
+
+Typecode SchemaProperty::getType() const
+{
+    return impl->getType();
+}
+
+Access SchemaProperty::getAccess() const
+{
+    return impl->getAccess();
+}
+
+bool SchemaProperty::isIndex() const
+{
+    return impl->isIndex();
+}
+
+bool SchemaProperty::isOptional() const
+{
+    return impl->isOptional();
+}
+
+const char* SchemaProperty::getUnit() const
+{
+    return impl->getUnit().c_str();
+}
+
+const char* SchemaProperty::getDesc() const
+{
+    return impl->getDesc().c_str();
+}
+
+SchemaStatistic::SchemaStatistic(const char* name, Typecode typecode)
+{
+    impl = new SchemaStatisticImpl(this, name, typecode);
+}
+
+SchemaStatistic::SchemaStatistic(SchemaStatisticImpl* i) : impl(i) {}
+
+SchemaStatistic::~SchemaStatistic()
+{
+    delete impl;
+}
+
+void SchemaStatistic::setUnit(const char* val)
+{
+    impl->setUnit(val);
+}
+
+void SchemaStatistic::setDesc(const char* desc)
+{
+    impl->setDesc(desc);
+}
+
+const char* SchemaStatistic::getName() const
+{
+    return impl->getName().c_str();
+}
+
+Typecode SchemaStatistic::getType() const
+{
+    return impl->getType();
+}
+
+const char* SchemaStatistic::getUnit() const
+{
+    return impl->getUnit().c_str();
+}
+
+const char* SchemaStatistic::getDesc() const
+{
+    return impl->getDesc().c_str();
+}
+
+SchemaObjectClass::SchemaObjectClass(const char* package, const char* name)
+{
+    impl = new SchemaObjectClassImpl(this, package, name);
+}
+
+SchemaObjectClass::SchemaObjectClass(SchemaObjectClassImpl* i) : impl(i) {}
+
+SchemaObjectClass::~SchemaObjectClass()
+{
+    delete impl;
+}
+
+void SchemaObjectClass::addProperty(const SchemaProperty& property)
+{
+    impl->addProperty(property);
+}
+
+void SchemaObjectClass::addStatistic(const SchemaStatistic& statistic)
+{
+    impl->addStatistic(statistic);
+}
+
+void SchemaObjectClass::addMethod(const SchemaMethod& method)
+{
+    impl->addMethod(method);
+}
+
+const char* SchemaObjectClass::getPackage() const
+{
+    return impl->getPackage().c_str();
+}
+
+const char* SchemaObjectClass::getName() const
+{
+    return impl->getName().c_str();
+}
+
+const uint8_t* SchemaObjectClass::getHash() const
+{
+    return impl->getHash();
+}
+
+int SchemaObjectClass::getPropertyCount() const
+{
+    return impl->getPropertyCount();
+}
+
+int SchemaObjectClass::getStatisticCount() const
+{
+    return impl->getStatisticCount();
+}
+
+int SchemaObjectClass::getMethodCount() const
+{
+    return impl->getMethodCount();
+}
+
+const SchemaProperty* SchemaObjectClass::getProperty(int idx) const
+{
+    return impl->getProperty(idx);
+}
+
+const SchemaStatistic* SchemaObjectClass::getStatistic(int idx) const
+{
+    return impl->getStatistic(idx);
+}
+
+const SchemaMethod* SchemaObjectClass::getMethod(int idx) const
+{
+    return impl->getMethod(idx);
+}
+
+SchemaEventClass::SchemaEventClass(const char* package, const char* name)
+{
+    impl = new SchemaEventClassImpl(this, package, name);
+}
+
+SchemaEventClass::SchemaEventClass(SchemaEventClassImpl* i) : impl(i) {}
+
+SchemaEventClass::~SchemaEventClass()
+{
+    delete impl;
+}
+
+void SchemaEventClass::addArgument(const SchemaArgument& argument)
+{
+    impl->addArgument(argument);
+}
+
+void SchemaEventClass::setDesc(const char* desc)
+{
+    impl->setDesc(desc);
+}
+
+const char* SchemaEventClass::getPackage() const
+{
+    return impl->getPackage().c_str();
+}
+
+const char* SchemaEventClass::getName() const
+{
+    return impl->getName().c_str();
+}
+
+const uint8_t* SchemaEventClass::getHash() const
+{
+    return impl->getHash();
+}
+
+int SchemaEventClass::getArgumentCount() const
+{
+    return impl->getArgumentCount();
+}
+
+const SchemaArgument* SchemaEventClass::getArgument(int idx) const
+{
+    return impl->getArgument(idx);
+}
+

Added: qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.h?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.h (added)
+++ qpid/trunk/qpid/cpp/src/qmf/SchemaImpl.h Fri May 22 21:40:57 2009
@@ -0,0 +1,195 @@
+#ifndef _QmfSchemaImpl_
+#define _QmfSchemaImpl_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "Schema.h"
+#include <string>
+#include <vector>
+#include <qpid/framing/Buffer.h>
+
+namespace qmf {
+
+    // TODO: Destructors for schema classes
+    // TODO: Add "frozen" attribute for schema classes so they can't be modified after
+    //       they've been registered.
+
+    class SchemaHash {
+        uint8_t hash[16];
+    public:
+        SchemaHash();
+        void encode(qpid::framing::Buffer& buffer);
+        void decode(qpid::framing::Buffer& buffer);
+        void update(const char* data, uint32_t len);
+        void update(uint8_t data);
+        void update(const std::string& data) { update(data.c_str(), data.size()); }
+        void update(Typecode t) { update((uint8_t) t); }
+        void update(Direction d) { update((uint8_t) d); }
+        void update(Access a) { update((uint8_t) a); }
+        void update(bool b) { update((uint8_t) (b ? 1 : 0)); }
+        const uint8_t* get() const { return hash; }
+    };
+
+    struct SchemaArgumentImpl {
+        SchemaArgument* envelope;
+        std::string name;
+        Typecode typecode;
+        Direction dir;
+        std::string unit;
+        std::string description;
+
+        SchemaArgumentImpl(SchemaArgument* e, const char* n, Typecode t) :
+            envelope(e), name(n), typecode(t), dir(DIR_IN) {}
+        SchemaArgumentImpl(qpid::framing::Buffer& buffer);
+        void encode(qpid::framing::Buffer& buffer) const;
+        void setDirection(Direction d) { dir = d; }
+        void setUnit(const char* val) { unit = val; }
+        void setDesc(const char* desc) { description = desc; }
+        const std::string& getName() const { return name; }
+        Typecode getType() const { return typecode; }
+        Direction getDirection() const { return dir; }
+        const std::string& getUnit() const { return unit; }
+        const std::string& getDesc() const { return description; }
+        void updateHash(SchemaHash& hash) const;
+    };
+
+    struct SchemaMethodImpl {
+        SchemaMethod* envelope;
+        std::string name;
+        std::string description;
+        std::vector<SchemaArgumentImpl*> arguments;
+
+        SchemaMethodImpl(SchemaMethod* e, const char* n) : envelope(e), name(n) {}
+        SchemaMethodImpl(qpid::framing::Buffer& buffer);
+        void encode(qpid::framing::Buffer& buffer) const;
+        void addArgument(const SchemaArgument& argument);
+        void setDesc(const char* desc) { description = desc; }
+        const std::string& getName() const { return name; }
+        const std::string& getDesc() const { return description; }
+        int getArgumentCount() const { return arguments.size(); }
+        const SchemaArgument* getArgument(int idx) const;
+        void updateHash(SchemaHash& hash) const;
+    };
+
+    struct SchemaPropertyImpl {
+        SchemaProperty* envelope;
+        std::string name;
+        Typecode typecode;
+        Access access;
+        bool index;
+        bool optional;
+        std::string unit;
+        std::string description;
+
+        SchemaPropertyImpl(SchemaProperty* e, const char* n, Typecode t) :
+            envelope(e), name(n), typecode(t), access(ACCESS_READ_ONLY),
+            index(false), optional(false) {}
+        SchemaPropertyImpl(qpid::framing::Buffer& buffer);
+        void encode(qpid::framing::Buffer& buffer) const;
+        void setAccess(Access a) { access = a; }
+        void setIndex(bool val) { index = val; }
+        void setOptional(bool val) { optional = val; }
+        void setUnit(const char* val) { unit = val; }
+        void setDesc(const char* desc) { description = desc; }
+        const std::string& getName() const { return name; }
+        Typecode getType() const { return typecode; }
+        Access getAccess() const { return access; }
+        bool isIndex() const { return index; }
+        bool isOptional() const { return optional; }
+        const std::string& getUnit() const { return unit; }
+        const std::string& getDesc() const { return description; }
+        void updateHash(SchemaHash& hash) const;
+    };
+
+    struct SchemaStatisticImpl {
+        SchemaStatistic* envelope;
+        std::string name;
+        Typecode typecode;
+        std::string unit;
+        std::string description;
+
+        SchemaStatisticImpl(SchemaStatistic* e, const char* n, Typecode t) :
+            envelope(e), name(n), typecode(t) {}
+        SchemaStatisticImpl(qpid::framing::Buffer& buffer);
+        void encode(qpid::framing::Buffer& buffer) const;
+        void setUnit(const char* val) { unit = val; }
+        void setDesc(const char* desc) { description = desc; }
+        const std::string& getName() const { return name; }
+        Typecode getType() const { return typecode; }
+        const std::string& getUnit() const { return unit; }
+        const std::string& getDesc() const { return description; }
+        void updateHash(SchemaHash& hash) const;
+    };
+
+    struct SchemaObjectClassImpl {
+        SchemaObjectClass* envelope;
+        std::string package;
+        std::string name;
+        mutable SchemaHash hash;
+        mutable bool hasHash;
+        std::vector<SchemaPropertyImpl*> properties;
+        std::vector<SchemaStatisticImpl*> statistics;
+        std::vector<SchemaMethodImpl*> methods;
+
+        SchemaObjectClassImpl(SchemaObjectClass* e, const char* p, const char* n) :
+            envelope(e), package(p), name(n), hasHash(false) {}
+        SchemaObjectClassImpl(qpid::framing::Buffer& buffer);
+        void encode(qpid::framing::Buffer& buffer) const;
+        void addProperty(const SchemaProperty& property);
+        void addStatistic(const SchemaStatistic& statistic);
+        void addMethod(const SchemaMethod& method);
+
+        const std::string& getPackage() const { return package; }
+        const std::string& getName() const { return name; }
+        const uint8_t* getHash() const;
+        int getPropertyCount() const { return properties.size(); }
+        int getStatisticCount() const { return statistics.size(); }
+        int getMethodCount() const { return methods.size(); }
+        const SchemaProperty* getProperty(int idx) const;
+        const SchemaStatistic* getStatistic(int idx) const;
+        const SchemaMethod* getMethod(int idx) const;
+    };
+
+    struct SchemaEventClassImpl {
+        SchemaEventClass* envelope;
+        std::string package;
+        std::string name;
+        mutable SchemaHash hash;
+        mutable bool hasHash;
+        std::string description;
+        std::vector<SchemaArgumentImpl*> arguments;
+
+        SchemaEventClassImpl(SchemaEventClass* e, const char* p, const char* n) :
+            envelope(e), package(p), name(n), hasHash(false) {}
+        SchemaEventClassImpl(qpid::framing::Buffer& buffer);
+        void encode(qpid::framing::Buffer& buffer) const;
+        void addArgument(const SchemaArgument& argument);
+        void setDesc(const char* desc) { description = desc; }
+
+        const std::string& getPackage() const { return package; }
+        const std::string& getName() const { return name; }
+        const uint8_t* getHash() const;
+        int getArgumentCount() const { return arguments.size(); }
+        const SchemaArgument* getArgument(int idx) const;
+    };
+}
+
+#endif
+

Added: qpid/trunk/qpid/cpp/src/qmf/Typecode.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/Typecode.h?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/Typecode.h (added)
+++ qpid/trunk/qpid/cpp/src/qmf/Typecode.h Fri May 22 21:40:57 2009
@@ -0,0 +1,51 @@
+#ifndef _QmfTypecode_
+#define _QmfTypecode_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+namespace qmf {
+
+    enum Typecode {
+        TYPE_UINT8      = 1,
+        TYPE_UINT16     = 2,
+        TYPE_UINT32     = 3,
+        TYPE_UINT64     = 4,
+        TYPE_SSTR       = 6,
+        TYPE_LSTR       = 7,
+        TYPE_ABSTIME    = 8,
+        TYPE_DELTATIME  = 9,
+        TYPE_REF        = 10,
+        TYPE_BOOL       = 11,
+        TYPE_FLOAT      = 12,
+        TYPE_DOUBLE     = 13,
+        TYPE_UUID       = 14,
+        TYPE_MAP        = 15,
+        TYPE_INT8       = 16,
+        TYPE_INT16      = 17,
+        TYPE_INT32      = 18,
+        TYPE_INT64      = 19,
+        TYPE_OBJECT     = 20,
+        TYPE_LIST       = 21,
+        TYPE_ARRAY      = 22
+    };
+}
+
+#endif
+

Added: qpid/trunk/qpid/cpp/src/qmf/Value.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/Value.h?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/Value.h (added)
+++ qpid/trunk/qpid/cpp/src/qmf/Value.h Fri May 22 21:40:57 2009
@@ -0,0 +1,113 @@
+#ifndef _QmfValue_
+#define _QmfValue_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <qmf/ObjectId.h>
+#include <qmf/Typecode.h>
+
+namespace qmf {
+
+    class Object;
+    class ValueImpl;
+
+    class Value {
+    public:
+        Value();
+        Value(Typecode t, Typecode arrayType = TYPE_UINT8);
+        Value(ValueImpl* impl);
+        ~Value();
+
+        Typecode getType() const;
+        bool isNull() const;
+        void setNull();
+
+        bool isObjectId() const;
+        const ObjectId& asObjectId() const;
+        void setObjectId(const ObjectId& oid);
+
+        bool isUint() const;
+        uint32_t asUint() const;
+        void setUint(uint32_t val);
+
+        bool isInt() const;
+        int32_t asInt() const;
+        void setInt(int32_t val);
+
+        bool isUint64() const;
+        uint64_t asUint64() const;
+        void setUint64(uint64_t val);
+
+        bool isInt64() const;
+        int64_t asInt64() const;
+        void setInt64(int64_t val);
+
+        bool isString() const;
+        const char* asString() const;
+        void setString(const char* val);
+
+        bool isBool() const;
+        bool asBool() const;
+        void setBool(bool val);
+
+        bool isFloat() const;
+        float asFloat() const;
+        void setFloat(float val);
+
+        bool isDouble() const;
+        double asDouble() const;
+        void setDouble(double val);
+
+        bool isUuid() const;
+        const uint8_t* asUuid() const;
+        void setUuid(const uint8_t* val);
+
+        bool isObject() const;
+        Object* asObject() const;
+        void setObject(Object* val);
+
+        bool isMap() const;
+        bool keyInMap(const char* key) const;
+        Value* byKey(const char* key);
+        const Value* byKey(const char* key) const;
+        void deleteKey(const char* key);
+        void insert(const char* key, Value* val);
+        uint32_t keyCount() const;
+        const char* key(uint32_t idx) const;
+
+        bool isList() const;
+        uint32_t listItemCount() const;
+        Value* listItem(uint32_t idx);
+        void appendToList(Value* val);
+        void deleteListItem(uint32_t idx);
+
+        bool isArray() const;
+        Typecode arrayType() const;
+        uint32_t arrayItemCount() const;
+        Value* arrayItem(uint32_t idx);
+        void appendToArray(Value* val);
+        void deleteArrayItem(uint32_t idx);
+
+        ValueImpl* impl;
+    };
+}
+
+#endif
+

Added: qpid/trunk/qpid/cpp/src/qmf/ValueImpl.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/ValueImpl.cpp?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/ValueImpl.cpp (added)
+++ qpid/trunk/qpid/cpp/src/qmf/ValueImpl.cpp Fri May 22 21:40:57 2009
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "ValueImpl.h"
+#include <qpid/framing/FieldTable.h>
+
+using namespace std;
+using namespace qmf;
+using qpid::framing::Buffer;
+
+ValueImpl::ValueImpl(Typecode t, Buffer& buf) : envelope(new Value(this)), typecode(t)
+{
+    uint64_t first;
+    uint64_t second;
+    qpid::framing::FieldTable ft;
+
+    switch (typecode) {
+    case TYPE_UINT8     : value.u32 = (uint32_t) buf.getOctet();  break;
+    case TYPE_UINT16    : value.u32 = (uint32_t) buf.getShort();  break;
+    case TYPE_UINT32    : value.u32 = (uint32_t) buf.getLong();   break;
+    case TYPE_UINT64    : value.u64 = buf.getLongLong();          break;
+    case TYPE_SSTR      : buf.getShortString(stringVal);          break;
+    case TYPE_LSTR      : buf.getMediumString(stringVal);         break;
+    case TYPE_ABSTIME   : value.s64 = buf.getLongLong();          break;
+    case TYPE_DELTATIME : value.u64 = buf.getLongLong();          break;
+    case TYPE_BOOL      : value.boolVal = (buf.getOctet() != 0);  break;
+    case TYPE_FLOAT     : value.floatVal = buf.getFloat();        break;
+    case TYPE_DOUBLE    : value.doubleVal = buf.getDouble();      break;
+    case TYPE_INT8      : value.s32 = (int32_t) buf.getOctet();   break;
+    case TYPE_INT16     : value.s32 = (int32_t) buf.getShort();   break;
+    case TYPE_INT32     : value.s32 = (int32_t) buf.getLong();    break;
+    case TYPE_INT64     : value.s64 = buf.getLongLong();          break;
+    case TYPE_UUID      : buf.getBin128(value.uuidVal);           break;
+    case TYPE_REF:
+        first = buf.getLongLong();
+        second = buf.getLongLong();
+        refVal.impl->setValue(first, second);
+        break;
+
+    case TYPE_MAP:
+        ft.decode(buf);
+        // TODO: either update to recursively use QMF types or reduce to int/string/...
+        // (maybe use another ctor with a FieldValue argument)
+        break;
+
+    case TYPE_LIST:
+    case TYPE_ARRAY:
+    case TYPE_OBJECT:
+    default:
+        break;
+    }
+}
+
+ValueImpl::ValueImpl(Typecode t) : envelope(new Value(this)), typecode(t)
+{
+    ::memset(&value, 0, sizeof(value));
+}
+
+ValueImpl::~ValueImpl()
+{
+}
+
+void ValueImpl::encode(Buffer& buf) const
+{
+    switch (typecode) {
+    case TYPE_UINT8     : buf.putOctet((uint8_t) value.u32);        break;
+    case TYPE_UINT16    : buf.putShort((uint16_t) value.u32);       break;
+    case TYPE_UINT32    : buf.putLong(value.u32);                   break;
+    case TYPE_UINT64    : buf.putLongLong(value.u64);               break;
+    case TYPE_SSTR      : buf.putShortString(stringVal);            break;
+    case TYPE_LSTR      : buf.putMediumString(stringVal);           break;
+    case TYPE_ABSTIME   : buf.putLongLong(value.s64);               break;
+    case TYPE_DELTATIME : buf.putLongLong(value.u64);               break;
+    case TYPE_BOOL      : buf.putOctet(value.boolVal ? 1 : 0);      break;
+    case TYPE_FLOAT     : buf.putFloat(value.floatVal);             break;
+    case TYPE_DOUBLE    : buf.putDouble(value.doubleVal);           break;
+    case TYPE_INT8      : buf.putOctet((uint8_t) value.s32);        break;
+    case TYPE_INT16     : buf.putShort((uint16_t) value.s32);       break;
+    case TYPE_INT32     : buf.putLong(value.s32);                   break;
+    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_LIST:
+    case TYPE_ARRAY:
+    case TYPE_OBJECT:
+    default:
+        break;
+    }
+}
+
+bool ValueImpl::keyInMap(const char* key) const
+{
+    return typecode == TYPE_MAP && mapVal.count(key) > 0;
+}
+
+Value* ValueImpl::byKey(const char* key)
+{
+    if (keyInMap(key)) {
+        map<std::string, VPtr>::iterator iter = mapVal.find(key);
+        if (iter != mapVal.end())
+            return iter->second.get();
+    }
+    return 0;
+}
+
+const Value* ValueImpl::byKey(const char* key) const
+{
+    if (keyInMap(key)) {
+        map<std::string, VPtr>::const_iterator iter = mapVal.find(key);
+        if (iter != mapVal.end())
+            return iter->second.get();
+    }
+    return 0;
+}
+
+void ValueImpl::deleteKey(const char* key)
+{
+    mapVal.erase(key);
+}
+
+void ValueImpl::insert(const char* key, Value* val)
+{
+    mapVal[key] = VPtr(val);
+}
+
+const char* ValueImpl::key(uint32_t idx) const
+{
+    map<std::string, VPtr>::const_iterator iter = mapVal.begin();
+    for (uint32_t i = 0; i < idx; i++) {
+        if (iter == mapVal.end())
+            break;
+        iter++;
+    }
+
+    if (iter == mapVal.end())
+        return 0;
+    else
+        return iter->first.c_str();
+}
+
+Value* ValueImpl::listItem(uint32_t)
+{
+    return 0;
+}
+
+void ValueImpl::appendToList(Value*)
+{
+}
+
+void ValueImpl::deleteListItem(uint32_t)
+{
+}
+
+Value* ValueImpl::arrayItem(uint32_t)
+{
+    return 0;
+}
+
+void ValueImpl::appendToArray(Value*)
+{
+}
+
+void ValueImpl::deleteArrayItem(uint32_t)
+{
+}
+
+
+//==================================================================
+// Wrappers
+//==================================================================
+
+Value::Value(Typecode t, Typecode at)
+{
+    impl = new ValueImpl(this, t, at);
+}
+
+Value::Value(ValueImpl* i)
+{
+    impl = i;
+}
+
+Value::~Value()
+{
+    delete impl;
+}
+
+Typecode Value::getType() const
+{
+    return impl->getType();
+}
+
+bool Value::isNull() const
+{
+    return impl->isNull();
+}
+
+void Value::setNull()
+{
+    impl->setNull();
+}
+
+bool Value::isObjectId() const
+{
+    return impl->isObjectId();
+}
+
+const ObjectId& Value::asObjectId() const
+{
+    return impl->asObjectId();
+}
+
+void Value::setObjectId(const ObjectId& oid)
+{
+    impl->setObjectId(oid);
+}
+
+bool Value::isUint() const
+{
+    return impl->isUint();
+}
+
+uint32_t Value::asUint() const
+{
+    return impl->asUint();
+}
+
+void Value::setUint(uint32_t val)
+{
+    impl->setUint(val);
+}
+
+bool Value::isInt() const
+{
+    return impl->isInt();
+}
+
+int32_t Value::asInt() const
+{
+    return impl->asInt();
+}
+
+void Value::setInt(int32_t val)
+{
+    impl->setInt(val);
+}
+
+bool Value::isUint64() const
+{
+    return impl->isUint64();
+}
+
+uint64_t Value::asUint64() const
+{
+    return impl->asUint64();
+}
+
+void Value::setUint64(uint64_t val)
+{
+    impl->setUint64(val);
+}
+
+bool Value::isInt64() const
+{
+    return impl->isInt64();
+}
+
+int64_t Value::asInt64() const
+{
+    return impl->asInt64();
+}
+
+void Value::setInt64(int64_t val)
+{
+    impl->setInt64(val);
+}
+
+bool Value::isString() const
+{
+    return impl->isString();
+}
+
+const char* Value::asString() const
+{
+    return impl->asString();
+}
+
+void Value::setString(const char* val)
+{
+    impl->setString(val);
+}
+
+bool Value::isBool() const
+{
+    return impl->isBool();
+}
+
+bool Value::asBool() const
+{
+    return impl->asBool();
+}
+
+void Value::setBool(bool val)
+{
+    impl->setBool(val);
+}
+
+bool Value::isFloat() const
+{
+    return impl->isFloat();
+}
+
+float Value::asFloat() const
+{
+    return impl->asFloat();
+}
+
+void Value::setFloat(float val)
+{
+    impl->setFloat(val);
+}
+
+bool Value::isDouble() const
+{
+    return impl->isDouble();
+}
+
+double Value::asDouble() const
+{
+    return impl->asDouble();
+}
+
+void Value::setDouble(double val)
+{
+    impl->setDouble(val);
+}
+
+bool Value::isUuid() const
+{
+    return impl->isUuid();
+}
+
+const uint8_t* Value::asUuid() const
+{
+    return impl->asUuid();
+}
+
+void Value::setUuid(const uint8_t* val)
+{
+    impl->setUuid(val);
+}
+
+bool Value::isObject() const
+{
+    return impl->isObject();
+}
+
+Object* Value::asObject() const
+{
+    return impl->asObject();
+}
+
+void Value::setObject(Object* val)
+{
+    impl->setObject(val);
+}
+
+bool Value::isMap() const
+{
+    return impl->isMap();
+}
+
+bool Value::keyInMap(const char* key) const
+{
+    return impl->keyInMap(key);
+}
+
+Value* Value::byKey(const char* key)
+{
+    return impl->byKey(key);
+}
+
+const Value* Value::byKey(const char* key) const
+{
+    return impl->byKey(key);
+}
+
+void Value::deleteKey(const char* key)
+{
+    impl->deleteKey(key);
+}
+
+void Value::insert(const char* key, Value* val)
+{
+    impl->insert(key, val);
+}
+
+uint32_t Value::keyCount() const
+{
+    return impl->keyCount();
+}
+
+const char* Value::key(uint32_t idx) const
+{
+    return impl->key(idx);
+}
+
+bool Value::isList() const
+{
+    return impl->isList();
+}
+
+uint32_t Value::listItemCount() const
+{
+    return impl->listItemCount();
+}
+
+Value* Value::listItem(uint32_t idx)
+{
+    return impl->listItem(idx);
+}
+
+void Value::appendToList(Value* val)
+{
+    impl->appendToList(val);
+}
+
+void Value::deleteListItem(uint32_t idx)
+{
+    impl->deleteListItem(idx);
+}
+
+bool Value::isArray() const
+{
+    return impl->isArray();
+}
+
+Typecode Value::arrayType() const
+{
+    return impl->arrayType();
+}
+
+uint32_t Value::arrayItemCount() const
+{
+    return impl->arrayItemCount();
+}
+
+Value* Value::arrayItem(uint32_t idx)
+{
+    return impl->arrayItem(idx);
+}
+
+void Value::appendToArray(Value* val)
+{
+    impl->appendToArray(val);
+}
+
+void Value::deleteArrayItem(uint32_t idx)
+{
+    impl->deleteArrayItem(idx);
+}
+

Added: qpid/trunk/qpid/cpp/src/qmf/ValueImpl.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qmf/ValueImpl.h?rev=777720&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qmf/ValueImpl.h (added)
+++ qpid/trunk/qpid/cpp/src/qmf/ValueImpl.h Fri May 22 21:40:57 2009
@@ -0,0 +1,144 @@
+#ifndef _QmfValueImpl_
+#define _QmfValueImpl_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <qmf/Value.h>
+#include <qmf/ObjectIdImpl.h>
+#include <qmf/Object.h>
+#include <qpid/framing/Buffer.h>
+#include <string>
+#include <string.h>
+#include <map>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+namespace qmf {
+
+    // TODO: set valid flag on all value settors
+    // TODO: add a modified flag and accessors
+
+    struct ValueImpl {
+        typedef boost::shared_ptr<Value> VPtr;
+        typedef boost::shared_ptr<Object> OPtr;
+        Value* envelope;
+        const Typecode typecode;
+        bool valid;
+
+        ObjectId refVal;
+        std::string stringVal;
+        OPtr objectVal;
+        std::map<std::string, VPtr> mapVal;
+        std::vector<VPtr> vectorVal;
+        Typecode arrayTypecode;
+
+        union {
+            uint32_t u32;
+            uint64_t u64;
+            int32_t  s32;
+            int64_t  s64;
+            bool     boolVal;
+            float    floatVal;
+            double   doubleVal;
+            uint8_t  uuidVal[16];
+        } value;
+
+        ValueImpl(Value* e, Typecode t, Typecode at) :
+            envelope(e), typecode(t), valid(false), arrayTypecode(at) {}
+        ValueImpl(Typecode t, qpid::framing::Buffer& b);
+        ValueImpl(Typecode t);
+        ~ValueImpl();
+
+        void encode(qpid::framing::Buffer& b) const;
+
+        Typecode getType() const { return typecode; }
+        bool isNull() const { return !valid; }
+        void setNull() { valid = false; }
+
+        bool isObjectId() const { return typecode == TYPE_REF; }
+        const ObjectId& asObjectId() const { return refVal; }
+        void setObjectId(const ObjectId& o) { refVal = o; }  // TODO
+
+        bool isUint() const { return typecode >= TYPE_UINT8 && typecode <= TYPE_UINT32; }
+        uint32_t asUint() const { return value.u32; }
+        void setUint(uint32_t val) { value.u32 = val; }
+
+        bool isInt() const { return typecode >= TYPE_INT8 && typecode <= TYPE_INT32; }
+        int32_t asInt() const { return value.s32; }
+        void setInt(int32_t val) { value.s32 = val; }
+
+        bool isUint64() const { return typecode == TYPE_UINT64 || typecode == TYPE_DELTATIME; }
+        uint64_t asUint64() const { return value.u64; }
+        void setUint64(uint64_t val) { value.u64 = val; }
+
+        bool isInt64() const { return typecode == TYPE_INT64 || typecode == TYPE_ABSTIME; }
+        int64_t asInt64() const { return value.s64; }
+        void setInt64(int64_t val) { value.s64 = val; }
+
+        bool isString() const { return typecode == TYPE_SSTR || typecode == TYPE_LSTR; }
+        const char* asString() const { return stringVal.c_str(); }
+        void setString(const char* val) { stringVal = val; }
+
+        bool isBool() const { return typecode == TYPE_BOOL; }
+        bool asBool() const { return value.boolVal; }
+        void setBool(bool val) { value.boolVal = val; }
+
+        bool isFloat() const { return typecode == TYPE_FLOAT; }
+        float asFloat() const { return value.floatVal; }
+        void setFloat(float val) { value.floatVal = val; }
+
+        bool isDouble() const { return typecode == TYPE_DOUBLE; }
+        double asDouble() const { return value.doubleVal; }
+        void setDouble(double val) { value.doubleVal = val; }
+
+        bool isUuid() const { return typecode == TYPE_UUID; }
+        const uint8_t* asUuid() const { return value.uuidVal; }
+        void setUuid(const uint8_t* val) { ::memcpy(value.uuidVal, val, 16); }
+
+        bool isObject() const { return typecode == TYPE_OBJECT; }
+        Object* asObject() const { return objectVal.get(); }
+        void setObject(Object* val) { objectVal.reset(val); }
+
+        bool isMap() const { return typecode == TYPE_MAP; }
+        bool keyInMap(const char* key) const;
+        Value* byKey(const char* key);
+        const Value* byKey(const char* key) const;
+        void deleteKey(const char* key);
+        void insert(const char* key, Value* val);
+        uint32_t keyCount() const { return mapVal.size(); }
+        const char* key(uint32_t idx) const;
+
+        bool isList() const { return typecode == TYPE_LIST; }
+        uint32_t listItemCount() const { return vectorVal.size(); }
+        Value* listItem(uint32_t idx);
+        void appendToList(Value* val);
+        void deleteListItem(uint32_t idx);
+
+        bool isArray() const { return typecode == TYPE_ARRAY; }
+        Typecode arrayType() const { return arrayTypecode; }
+        uint32_t arrayItemCount() const { return vectorVal.size(); }
+        Value* arrayItem(uint32_t idx);
+        void appendToArray(Value* val);
+        void deleteArrayItem(uint32_t idx);
+    };
+}
+
+#endif
+



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org