summaryrefslogtreecommitdiff
path: root/qpid/cpp/src/qmf/Schema.cpp
diff options
context:
space:
mode:
authorRajith Muditha Attapattu <rajith@apache.org>2011-05-27 15:44:23 +0000
committerRajith Muditha Attapattu <rajith@apache.org>2011-05-27 15:44:23 +0000
commit66765100f4257159622cefe57bed50125a5ad017 (patch)
treea88ee23bb194eb91f0ebb2d9b23ff423e3ea8e37 /qpid/cpp/src/qmf/Schema.cpp
parent1aeaa7b16e5ce54f10c901d75c4d40f9f88b9db6 (diff)
parent88b98b2f4152ef59a671fad55a0d08338b6b78ca (diff)
downloadqpid-python-66765100f4257159622cefe57bed50125a5ad017.tar.gz
Creating a branch for experimenting with some ideas for JMS client.rajith_jms_client
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/rajith_jms_client@1128369 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/src/qmf/Schema.cpp')
-rw-r--r--qpid/cpp/src/qmf/Schema.cpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/qpid/cpp/src/qmf/Schema.cpp b/qpid/cpp/src/qmf/Schema.cpp
new file mode 100644
index 0000000000..872aad724c
--- /dev/null
+++ b/qpid/cpp/src/qmf/Schema.cpp
@@ -0,0 +1,358 @@
+/*
+ *
+ * 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/SchemaImpl.h"
+#include "qmf/PrivateImplRef.h"
+#include "qmf/exceptions.h"
+#include "qmf/SchemaTypes.h"
+#include "qmf/SchemaIdImpl.h"
+#include "qmf/SchemaPropertyImpl.h"
+#include "qmf/SchemaMethodImpl.h"
+#include "qmf/Hash.h"
+#include "qpid/log/Statement.h"
+#include "qpid/management/Buffer.h"
+#include <list>
+
+using namespace std;
+using qpid::types::Variant;
+using namespace qmf;
+
+typedef PrivateImplRef<Schema> PI;
+
+Schema::Schema(SchemaImpl* impl) { PI::ctor(*this, impl); }
+Schema::Schema(const Schema& s) : qmf::Handle<SchemaImpl>() { PI::copy(*this, s); }
+Schema::~Schema() { PI::dtor(*this); }
+Schema& Schema::operator=(const Schema& s) { return PI::assign(*this, s); }
+
+Schema::Schema(int t, const string& p, const string& c) { PI::ctor(*this, new SchemaImpl(t, p, c)); }
+const SchemaId& Schema::getSchemaId() const { return impl->getSchemaId(); }
+void Schema::finalize() { impl->finalize(); }
+bool Schema::isFinalized() const { return impl->isFinalized(); }
+void Schema::addProperty(const SchemaProperty& p) { impl->addProperty(p); }
+void Schema::addMethod(const SchemaMethod& m) { impl->addMethod(m); }
+void Schema::setDesc(const string& d) { impl->setDesc(d); }
+const string& Schema::getDesc() const { return impl->getDesc(); }
+void Schema::setDefaultSeverity(int s) { impl->setDefaultSeverity(s); }
+int Schema::getDefaultSeverity() const { return impl->getDefaultSeverity(); }
+uint32_t Schema::getPropertyCount() const { return impl->getPropertyCount(); }
+SchemaProperty Schema::getProperty(uint32_t i) const { return impl->getProperty(i); }
+uint32_t Schema::getMethodCount() const { return impl->getMethodCount(); }
+SchemaMethod Schema::getMethod(uint32_t i) const { return impl->getMethod(i); }
+
+//========================================================================================
+// Impl Method Bodies
+//========================================================================================
+
+SchemaImpl::SchemaImpl(const Variant::Map& map) : finalized(false)
+{
+ Variant::Map::const_iterator iter;
+ Variant::List::const_iterator lIter;
+
+ iter = map.find("_schema_id");
+ if (iter == map.end())
+ throw QmfException("Schema map missing _schema_id element");
+ schemaId = SchemaId(new SchemaIdImpl(iter->second.asMap()));
+
+ iter = map.find("_desc");
+ if (iter != map.end())
+ description = iter->second.asString();
+
+ iter = map.find("_default_severity");
+ if (iter != map.end())
+ defaultSeverity = int(iter->second.asUint32());
+
+ iter = map.find("_properties");
+ if (iter != map.end()) {
+ const Variant::List& props(iter->second.asList());
+ for (lIter = props.begin(); lIter != props.end(); lIter++)
+ addProperty(SchemaProperty(new SchemaPropertyImpl(lIter->asMap())));
+ }
+
+ iter = map.find("_methods");
+ if (iter != map.end()) {
+ const Variant::List& meths(iter->second.asList());
+ for (lIter = meths.begin(); lIter != meths.end(); lIter++)
+ addMethod(SchemaMethod(new SchemaMethodImpl(lIter->asMap())));
+ }
+
+ finalized = true;
+}
+
+
+Variant::Map SchemaImpl::asMap() const
+{
+ Variant::Map map;
+ Variant::List propList;
+ Variant::List methList;
+
+ checkNotFinal();
+
+ map["_schema_id"] = SchemaIdImplAccess::get(schemaId).asMap();
+ if (!description.empty())
+ map["_desc"] = description;
+ if (schemaId.getType() == SCHEMA_TYPE_EVENT)
+ map["_default_severity"] = uint32_t(defaultSeverity);
+
+ for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++)
+ propList.push_back(SchemaPropertyImplAccess::get(*pIter).asMap());
+
+ for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++)
+ methList.push_back(SchemaMethodImplAccess::get(*mIter).asMap());
+
+ map["_properties"] = propList;
+ map["_methods"] = methList;
+ return map;
+}
+
+
+SchemaImpl::SchemaImpl(qpid::management::Buffer& buffer) : finalized(false)
+{
+ int schemaType;
+ string packageName;
+ string className;
+ uint8_t hash[16];
+
+ schemaType = int(buffer.getOctet());
+ buffer.getShortString(packageName);
+ buffer.getShortString(className);
+ buffer.getBin128(hash);
+ schemaId = SchemaId(schemaType, packageName, className);
+ schemaId.setHash(qpid::types::Uuid(hash));
+
+ if (schemaType == SCHEMA_TYPE_DATA) {
+ uint16_t propCount(buffer.getShort());
+ uint16_t statCount(buffer.getShort());
+ uint16_t methCount(buffer.getShort());
+ for (uint16_t idx = 0; idx < propCount + statCount; idx++)
+ addProperty(new SchemaPropertyImpl(buffer));
+ for (uint16_t idx = 0; idx < methCount; idx++)
+ addMethod(new SchemaMethodImpl(buffer));
+ }
+
+ finalized = true;
+}
+
+
+string SchemaImpl::asV1Content(uint32_t sequence) const
+{
+#define RAW_BUF_SIZE 65536
+ char rawBuf[RAW_BUF_SIZE];
+ qpid::management::Buffer buffer(rawBuf, RAW_BUF_SIZE);
+
+ //
+ // Encode the QMFv1 Header
+ //
+ buffer.putOctet('A');
+ buffer.putOctet('M');
+ buffer.putOctet('2');
+ buffer.putOctet('s');
+ buffer.putLong(sequence);
+
+ //
+ // Encode the common schema information
+ //
+ buffer.putOctet(uint8_t(schemaId.getType()));
+ buffer.putShortString(schemaId.getPackageName());
+ buffer.putShortString(schemaId.getName());
+ buffer.putBin128(schemaId.getHash().data());
+
+ if (schemaId.getType() == SCHEMA_TYPE_DATA) {
+ buffer.putShort(properties.size());
+ buffer.putShort(0);
+ buffer.putShort(methods.size());
+ for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++)
+ SchemaPropertyImplAccess::get(*pIter).encodeV1(buffer, false, false);
+ for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++)
+ SchemaMethodImplAccess::get(*mIter).encodeV1(buffer);
+ } else {
+ buffer.putShort(properties.size());
+ for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++)
+ SchemaPropertyImplAccess::get(*pIter).encodeV1(buffer, true, false);
+ }
+
+ return string(rawBuf, buffer.getPosition());
+}
+
+
+bool SchemaImpl::isValidProperty(const std::string& k, const Variant& v) const
+{
+ for (list<SchemaProperty>::const_iterator iter = properties.begin(); iter != properties.end(); iter++)
+ if (iter->getName() == k)
+ return (isCompatibleType(iter->getType(), v.getType()));
+ return false;
+}
+
+
+bool SchemaImpl::isValidMethodInArg(const std::string& m, const std::string& k, const Variant& v) const
+{
+ for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) {
+ if (mIter->getName() == m) {
+ uint32_t count(mIter->getArgumentCount());
+ for (uint32_t i = 0; i < count; i++) {
+ const SchemaProperty prop(mIter->getArgument(i));
+ if (prop.getName() == k) {
+ if (prop.getDirection() == DIR_IN || prop.getDirection() == DIR_IN_OUT)
+ return (isCompatibleType(prop.getType(), v.getType()));
+ else
+ return false;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+bool SchemaImpl::isValidMethodOutArg(const std::string& m, const std::string& k, const Variant& v) const
+{
+ for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) {
+ if (mIter->getName() == m) {
+ uint32_t count(mIter->getArgumentCount());
+ for (uint32_t i = 0; i < count; i++) {
+ const SchemaProperty prop(mIter->getArgument(i));
+ if (prop.getName() == k) {
+ if (prop.getDirection() == DIR_OUT || prop.getDirection() == DIR_IN_OUT)
+ return (isCompatibleType(prop.getType(), v.getType()));
+ else
+ return false;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+void SchemaImpl::finalize()
+{
+ Hash hash;
+
+ hash.update((uint8_t) schemaId.getType());
+ hash.update(schemaId.getPackageName());
+ hash.update(schemaId.getName());
+
+ for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++)
+ SchemaPropertyImplAccess::get(*pIter).updateHash(hash);
+ for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++)
+ SchemaMethodImplAccess::get(*mIter).updateHash(hash);
+
+ schemaId.setHash(hash.asUuid());
+ QPID_LOG(debug, "Schema Finalized: " << schemaId.getPackageName() << ":" << schemaId.getName() << ":" <<
+ schemaId.getHash());
+
+ finalized = true;
+}
+
+
+SchemaProperty SchemaImpl::getProperty(uint32_t i) const
+{
+ uint32_t count = 0;
+ for (list<SchemaProperty>::const_iterator iter = properties.begin(); iter != properties.end(); iter++)
+ if (count++ == i)
+ return *iter;
+ throw IndexOutOfRange();
+}
+
+
+SchemaMethod SchemaImpl::getMethod(uint32_t i) const
+{
+ uint32_t count = 0;
+ for (list<SchemaMethod>::const_iterator iter = methods.begin(); iter != methods.end(); iter++)
+ if (count++ == i)
+ return *iter;
+ throw IndexOutOfRange();
+}
+
+void SchemaImpl::checkFinal() const
+{
+ if (finalized)
+ throw QmfException("Modification of a finalized schema is forbidden");
+}
+
+
+void SchemaImpl::checkNotFinal() const
+{
+ if (!finalized)
+ throw QmfException("Schema is not yet finalized/registered");
+}
+
+
+bool SchemaImpl::isCompatibleType(int qmfType, qpid::types::VariantType qpidType) const
+{
+ bool typeValid(false);
+
+ switch (qpidType) {
+ case qpid::types::VAR_VOID:
+ if (qmfType == SCHEMA_DATA_VOID)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_BOOL:
+ if (qmfType == SCHEMA_DATA_BOOL)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_UINT8:
+ case qpid::types::VAR_UINT16:
+ case qpid::types::VAR_UINT32:
+ case qpid::types::VAR_UINT64:
+ case qpid::types::VAR_INT8:
+ case qpid::types::VAR_INT16:
+ case qpid::types::VAR_INT32:
+ case qpid::types::VAR_INT64:
+ if (qmfType == SCHEMA_DATA_INT)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_FLOAT:
+ case qpid::types::VAR_DOUBLE:
+ if (qmfType == SCHEMA_DATA_FLOAT)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_STRING:
+ if (qmfType == SCHEMA_DATA_STRING)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_MAP:
+ if (qmfType == SCHEMA_DATA_MAP)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_LIST:
+ if (qmfType == SCHEMA_DATA_LIST)
+ typeValid = true;
+ break;
+ case qpid::types::VAR_UUID:
+ if (qmfType == SCHEMA_DATA_UUID)
+ typeValid = true;
+ break;
+ }
+
+ return typeValid;
+}
+
+
+SchemaImpl& SchemaImplAccess::get(Schema& item)
+{
+ return *item.impl;
+}
+
+
+const SchemaImpl& SchemaImplAccess::get(const Schema& item)
+{
+ return *item.impl;
+}