blob: cae0e0da6833e220cc9dfaf4e402b353ceeb2dcd [file] [log] [blame]
/*
* 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/engine/ObjectImpl.h"
#include "qmf/engine/ValueImpl.h"
#include "qmf/engine/BrokerProxyImpl.h"
#include <qpid/sys/Time.h>
using namespace std;
using namespace qmf::engine;
using namespace qpid::sys;
using qpid::framing::Buffer;
ObjectImpl::ObjectImpl(const SchemaObjectClass* type) : objectClass(type), broker(0), createTime(uint64_t(Duration(now()))), destroyTime(0), lastUpdatedTime(createTime)
{
int propCount = objectClass->getPropertyCount();
int statCount = objectClass->getStatisticCount();
int idx;
for (idx = 0; idx < propCount; idx++) {
const SchemaProperty* prop = objectClass->getProperty(idx);
properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
}
for (idx = 0; idx < statCount; idx++) {
const SchemaStatistic* stat = objectClass->getStatistic(idx);
statistics[stat->getName()] = ValuePtr(new Value(stat->getType()));
}
}
ObjectImpl::ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed) :
objectClass(type), broker(b), createTime(0), destroyTime(0), lastUpdatedTime(0)
{
int idx;
if (managed) {
lastUpdatedTime = buffer.getLongLong();
createTime = buffer.getLongLong();
destroyTime = buffer.getLongLong();
objectId.reset(ObjectIdImpl::factory(buffer));
}
if (prop) {
int propCount = objectClass->getPropertyCount();
set<string> excludes;
parsePresenceMasks(buffer, excludes);
for (idx = 0; idx < propCount; idx++) {
const SchemaProperty* prop = objectClass->getProperty(idx);
if (excludes.count(prop->getName()) != 0) {
properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
} else {
Value* pval = ValueImpl::factory(prop->getType(), buffer);
properties[prop->getName()] = ValuePtr(pval);
}
}
}
if (stat) {
int statCount = objectClass->getStatisticCount();
for (idx = 0; idx < statCount; idx++) {
const SchemaStatistic* stat = objectClass->getStatistic(idx);
Value* sval = ValueImpl::factory(stat->getType(), buffer);
statistics[stat->getName()] = ValuePtr(sval);
}
}
}
Object* ObjectImpl::factory(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed)
{
ObjectImpl* impl(new ObjectImpl(type, b, buffer, prop, stat, managed));
return new Object(impl);
}
ObjectImpl::~ObjectImpl()
{
}
void ObjectImpl::destroy()
{
destroyTime = uint64_t(Duration(now()));
// TODO - flag deletion
}
Value* ObjectImpl::getValue(const string& key) const
{
map<string, ValuePtr>::const_iterator iter;
iter = properties.find(key);
if (iter != properties.end())
return iter->second.get();
iter = statistics.find(key);
if (iter != statistics.end())
return iter->second.get();
return 0;
}
void ObjectImpl::invokeMethod(const string& methodName, const Value* inArgs, void* context) const
{
if (broker != 0 && objectId.get() != 0)
broker->sendMethodRequest(objectId.get(), objectClass, methodName, inArgs, context);
}
void ObjectImpl::merge(const Object& from)
{
for (map<string, ValuePtr>::const_iterator piter = from.impl->properties.begin();
piter != from.impl->properties.end(); piter++)
properties[piter->first] = piter->second;
for (map<string, ValuePtr>::const_iterator siter = from.impl->statistics.begin();
siter != from.impl->statistics.end(); siter++)
statistics[siter->first] = siter->second;
}
void ObjectImpl::parsePresenceMasks(Buffer& buffer, set<string>& excludeList)
{
int propCount = objectClass->getPropertyCount();
excludeList.clear();
uint8_t bit = 0;
uint8_t mask = 0;
for (int idx = 0; idx < propCount; idx++) {
const SchemaProperty* prop = objectClass->getProperty(idx);
if (prop->isOptional()) {
if (bit == 0) {
mask = buffer.getOctet();
bit = 1;
}
if ((mask & bit) == 0)
excludeList.insert(string(prop->getName()));
if (bit == 0x80)
bit = 0;
else
bit = bit << 1;
}
}
}
void ObjectImpl::encodeSchemaKey(qpid::framing::Buffer& buffer) const
{
buffer.putShortString(objectClass->getClassKey()->getPackageName());
buffer.putShortString(objectClass->getClassKey()->getClassName());
buffer.putBin128(const_cast<uint8_t*>(objectClass->getClassKey()->getHash()));
}
void ObjectImpl::encodeManagedObjectData(qpid::framing::Buffer& buffer) const
{
buffer.putLongLong(lastUpdatedTime);
buffer.putLongLong(createTime);
buffer.putLongLong(destroyTime);
objectId->impl->encode(buffer);
}
void ObjectImpl::encodeProperties(qpid::framing::Buffer& buffer) const
{
int propCount = objectClass->getPropertyCount();
uint8_t bit = 0;
uint8_t mask = 0;
ValuePtr value;
for (int idx = 0; idx < propCount; idx++) {
const SchemaProperty* prop = objectClass->getProperty(idx);
if (prop->isOptional()) {
value = properties[prop->getName()];
if (bit == 0)
bit = 1;
if (!value->isNull())
mask |= bit;
if (bit == 0x80) {
buffer.putOctet(mask);
bit = 0;
mask = 0;
} else
bit = bit << 1;
}
}
if (bit != 0) {
buffer.putOctet(mask);
}
for (int idx = 0; idx < propCount; idx++) {
const SchemaProperty* prop = objectClass->getProperty(idx);
value = properties[prop->getName()];
if (!prop->isOptional() || !value->isNull()) {
value->impl->encode(buffer);
}
}
}
void ObjectImpl::encodeStatistics(qpid::framing::Buffer& buffer) const
{
int statCount = objectClass->getStatisticCount();
for (int idx = 0; idx < statCount; idx++) {
const SchemaStatistic* stat = objectClass->getStatistic(idx);
ValuePtr value = statistics[stat->getName()];
value->impl->encode(buffer);
}
}
//==================================================================
// Wrappers
//==================================================================
Object::Object(const SchemaObjectClass* type) : impl(new ObjectImpl(type)) {}
Object::Object(ObjectImpl* i) : impl(i) {}
Object::Object(const Object& from) : impl(new ObjectImpl(*(from.impl))) {}
Object::~Object() { delete impl; }
void Object::destroy() { impl->destroy(); }
const ObjectId* Object::getObjectId() const { return impl->getObjectId(); }
void Object::setObjectId(ObjectId* oid) { impl->setObjectId(oid); }
const SchemaObjectClass* Object::getClass() const { return impl->getClass(); }
Value* Object::getValue(const char* key) const { return impl->getValue(key); }
void Object::invokeMethod(const char* m, const Value* a, void* c) const { impl->invokeMethod(m, a, c); }
bool Object::isDeleted() const { return impl->isDeleted(); }
void Object::merge(const Object& from) { impl->merge(from); }