diff options
author | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
---|---|---|
committer | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
commit | 66765100f4257159622cefe57bed50125a5ad017 (patch) | |
tree | a88ee23bb194eb91f0ebb2d9b23ff423e3ea8e37 /qpid/cpp/src/qmf/Schema.cpp | |
parent | 1aeaa7b16e5ce54f10c901d75c4d40f9f88b9db6 (diff) | |
parent | 88b98b2f4152ef59a671fad55a0d08338b6b78ca (diff) | |
download | qpid-python-rajith_jms_client.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.cpp | 358 |
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; +} |