initial commit

This commit is contained in:
Blue 2018-08-05 00:46:25 +03:00 committed by Юрий Губич
commit 4b60ece582
327 changed files with 28286 additions and 0 deletions

36
lib/wModel/CMakeLists.txt Normal file
View file

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 2.8.12)
project(model)
find_package(Qt5Core REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(HEADERS
model.h
modelstring.h
list.h
vocabulary.h
attributes.h
icatalogue.h
catalogue.h
file/file.h
)
set(SOURCES
model.cpp
modelstring.cpp
list.cpp
vocabulary.cpp
attributes.cpp
icatalogue.cpp
catalogue.cpp
file/file.cpp
)
add_library(wModel STATIC ${HEADERS} ${SOURCES})
target_link_libraries(wModel Qt5::Core)
target_link_libraries(wModel wSocket)
target_link_libraries(wModel wDispatcher)
target_link_libraries(wModel wType)

60
lib/wModel/attributes.cpp Normal file
View file

@ -0,0 +1,60 @@
#include "attributes.h"
M::Attributes::Attributes(const W::Address p_address, QObject* parent):
M::Vocabulary(p_address, parent),
attributes(new Map())
{
}
M::Attributes::~Attributes()
{
delete attributes;
}
M::Model::ModelType M::Attributes::getType() const
{
return type;
}
void M::Attributes::addAttribute(const W::String& key, M::Model* model)
{
Map::const_iterator itr = attributes->find(key);
if (itr != attributes->end()) {
throw 1;
}
attributes->insert(std::make_pair(key, model));
addModel(model);
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"name", key);
vc->insert(u"address", model->getAddress());
vc->insert(u"type", W::Uint64(model->getType()));
insert(key, vc);
}
void M::Attributes::removeAttribute(const W::String& key)
{
Map::const_iterator itr = attributes->find(key);
if (itr == attributes->end()) {
throw 1;
}
M::Model* model = itr->second;
attributes->erase(itr);
erase(key);
removeModel(model);
delete model;
}
void M::Attributes::setAttribute(const W::String& key, const W::Object& value)
{
Map::const_iterator itr = attributes->find(key);
itr->second->set(value);
}
void M::Attributes::setAttribute(const W::String& key, W::Object* value)
{
Map::const_iterator itr = attributes->find(key);
itr->second->set(value);
}

32
lib/wModel/attributes.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef M_ATTRIBUTES_H
#define M_ATTRIBUTES_H
#include "vocabulary.h"
#include <wType/string.h>
#include <map>
namespace M {
class Attributes : public M::Vocabulary
{
public:
Attributes(const W::Address p_address, QObject* parent = 0);
~Attributes();
void addAttribute(const W::String& key, M::Model* model);
void removeAttribute(const W::String& key);
void setAttribute(const W::String& key, const W::Object& value);
void setAttribute(const W::String& key, W::Object* value);
M::Model::ModelType getType() const override;
static const M::Model::ModelType type = attributes;
private:
typedef std::map<W::String, M::Model*> Map;
Map* attributes;
};
}
#endif // ATTRIBUTES_H

66
lib/wModel/catalogue.cpp Normal file
View file

@ -0,0 +1,66 @@
#include "catalogue.h"
M::Catalogue::Catalogue(const W::Address p_address, QObject* parent):
ICatalogue(p_address, parent),
data()
{
}
M::Catalogue::~Catalogue()
{
}
uint64_t M::Catalogue::addElement(const W::Vocabulary& record)
{
uint64_t id = M::ICatalogue::addElement(record);
data.insert(std::make_pair(id, static_cast<W::Vocabulary*>(record.copy())));
return id;
}
void M::Catalogue::removeElement(uint64_t id)
{
M::ICatalogue::removeElement(id);
Data::const_iterator itr = data.find(id);
delete itr->second;
data.erase(itr);
}
void M::Catalogue::clear()
{
M::ICatalogue::clear();
data.clear();
}
W::Vocabulary * M::Catalogue::getElement(uint64_t id)
{
return static_cast<W::Vocabulary*>(data.at(id)->copy());
}
std::set<uint64_t> M::Catalogue::getAll() const
{
std::set<uint64_t> res;
Data::const_iterator itr = data.begin();
Data::const_iterator end = data.end();
for (; itr != end; ++itr) {
res.insert(itr->first);
}
return res;
}
void M::Catalogue::modifyElement(uint64_t id, const W::Vocabulary& newValue)
{
Data::iterator itr = data.find(id);
delete itr->second;
itr->second = static_cast<W::Vocabulary*>(newValue.copy());
}
uint64_t M::Catalogue::size() const
{
return data.size();
}

29
lib/wModel/catalogue.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef CATALOGUE_H
#define CATALOGUE_H
#include "icatalogue.h"
namespace M {
class Catalogue : public ICatalogue {
public:
Catalogue(const W::Address p_address, QObject* parent = 0);
~Catalogue();
uint64_t addElement(const W::Vocabulary & record) override;
void removeElement(uint64_t id) override;
void clear() override;
W::Vocabulary* getElement(uint64_t id) override;
void modifyElement(uint64_t id, const W::Vocabulary & newValue) override;
uint64_t size() const override;
protected:
std::set<uint64_t> getAll() const override;
private:
typedef std::map<uint64_t, W::Vocabulary*> Data;
Data data;
};
}
#endif // CATALOGUE_H

86
lib/wModel/file/file.cpp Normal file
View file

@ -0,0 +1,86 @@
#include "file.h"
#include <iostream>
QMimeDatabase M::File::mimeDB;
M::File::File(W::Blob* p_file, const W::Address& addr, QObject* parent):
M::Model(addr, parent),
additional(),
file(p_file)
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::File::_h_get);
W::Handler* getAdditional = W::Handler::create(address + W::Address({u"getAdditional"}), this, &M::File::_h_getAdditional);
addHandler(get);
addHandler(getAdditional);
}
M::File::~File()
{
delete file;
}
M::Model::ModelType M::File::getType() const
{
return type;
}
void M::File::initAdditional(const W::String& p_mime)
{
additional.clear();
additional.insert(u"size", new W::Uint64(file->size()));
additional.insert(u"mimeType", p_mime);
}
void M::File::set(const W::Object& value)
{
set(value.copy());
}
void M::File::set(W::Object* value)
{
delete file;
file = static_cast<W::Blob*>(value);
QMimeType mt = mimeDB.mimeTypeForData(file->byteArray());
initAdditional(W::String(mt.name().toStdString()));
W::Vocabulary* vc = static_cast<W::Vocabulary*>(additional.copy());
broadcast(vc, W::Address({u"getAdditional"}));
}
void M::File::h_getAdditional(const W::Event& ev)
{
W::Vocabulary* vc = static_cast<W::Vocabulary*>(additional.copy());
response(vc, W::Address({u"getAdditional"}), ev);
}
void M::File::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_getAdditional(ev);
}
void M::File::h_get(const W::Event& ev)
{
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"additional", additional.copy());
vc->insert(u"data", file->copy());
response(vc, W::Address({u"get"}), ev);
}
M::File * M::File::create(W::Blob* blob, const W::Address& addr, QObject* parent)
{
M::File* out;
QMimeType mt = mimeDB.mimeTypeForData(blob->byteArray());
out = new File(blob, addr, parent);
out->initAdditional(W::String(mt.name().toStdString()));
return out;
}

44
lib/wModel/file/file.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef FILE_H
#define FILE_H
/**
* @todo write docs
*/
#include <wModel/model.h>
#include <wType/blob.h>
#include <QtCore/QMimeDatabase>
namespace M {
class File: public Model {
protected:
File(W::Blob* p_file, const W::Address& addr, QObject* parent = 0);
public:
~File();
void set(const W::Object & value) override;
void set(W::Object * value) override;
M::Model::ModelType getType() const override;
static const M::Model::ModelType type = file;
static File* create(W::Blob* blob, const W::Address& addr, QObject* parent = 0);
protected:
virtual void initAdditional(const W::String& p_mime);
void h_subscribe(const W::Event & ev) override;
handler(get);
handler(getAdditional);
protected:
W::Vocabulary additional;
W::Blob* file;
static QMimeDatabase mimeDB;
};
}
#endif // FILE_H

469
lib/wModel/icatalogue.cpp Normal file
View file

@ -0,0 +1,469 @@
#include "icatalogue.h"
const std::set<uint64_t> M::ICatalogue::empty = std::set<uint64_t>();
M::ICatalogue::ICatalogue(const W::Address p_address, QObject* parent):
M::Model(p_address, parent),
subscribeMember(W::Handler::create(W::Address({}), this, &M::ICatalogue::_h_subscribeMember)),
indexes(),
lastIndex(0),
activeChildren()
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::ICatalogue::_h_get);
W::Handler* add = W::Handler::create(address + W::Address({u"add"}), this, &M::ICatalogue::_h_add);
W::Handler* update = W::Handler::create(address + W::Address({u"update"}), this, &M::ICatalogue::_h_update);
addHandler(get);
addHandler(add);
addHandler(update);
}
M::ICatalogue::~ICatalogue()
{
delete subscribeMember;
IndexMap::const_iterator itr = indexes.begin();
IndexMap::const_iterator end = indexes.end();
for (; itr != end; ++itr) {
delete itr->second;
}
}
void M::ICatalogue::clear()
{
lastIndex = 0;
IndexMap::const_iterator itr = indexes.begin();
IndexMap::const_iterator end = indexes.end();
for (; itr != end; ++itr) {
itr->second->clear();
}
if (registered) {
broadcast(new W::Vocabulary(), W::Address{u"clear"});
}
emit countChange(0);
}
void M::ICatalogue::addIndex(const W::String& fieldName, W::Object::objectType fieldType)
{
IndexMap::const_iterator itr = indexes.find(fieldName);
if (itr != indexes.end()) {
throw 2;
}
switch (fieldType) {
case W::Object::uint64:
indexes.insert(std::make_pair(fieldName, new Index<W::Uint64>()));
break;
case W::Object::string:
indexes.insert(std::make_pair(fieldName, new Index<W::String>()));
break;
default:
throw 3;
}
}
const std::set<uint64_t> & M::ICatalogue::find(const W::String& indexName, const W::Object& value) const
{
IndexMap::const_iterator itr = indexes.find(indexName);
if (itr == indexes.end()) {
throw 4;
}
return itr->second->find(value);
}
std::set<uint64_t> M::ICatalogue::find(const W::Vocabulary& value) const
{
W::Vector keys = value.keys();
int size = keys.length();
std::set<uint64_t> result;
bool first = true;
for (int i = 0; i < size; ++i) {
const W::String& key = static_cast<const W::String&>(keys.at(i));
IndexMap::const_iterator itr = indexes.find(key);
if (itr == indexes.end()) {
throw 4;
}
if (first) {
result = itr->second->find(value.at(key));
first = false;
} else {
std::set<uint64_t> copy = result;
result.clear();
const std::set<uint64_t>& current = itr->second->find(value.at(key));
std::set_intersection(copy.begin(), copy.end(), current.begin(), current.end(), std::inserter(result, result.end()));
}
if (result.empty()) {
break;
}
}
return result;
}
M::Model::ModelType M::ICatalogue::getType() const
{
return type;
}
uint64_t M::ICatalogue::addElement(const W::Vocabulary& record)
{
IndexMap::const_iterator itr = indexes.begin();
IndexMap::const_iterator end = indexes.end();
++lastIndex;
for (; itr != end; ++itr) {
itr->second->add(record.at(itr->first), lastIndex);
}
Map::const_iterator sItr = subscribers->begin();
Map::const_iterator sEnd = subscribers->end();
for (; sItr != sEnd; ++sItr) {
SMap::const_iterator oItr = sItr->second.begin();
SMap::const_iterator oEnd = sItr->second.end();
for (; oItr != oEnd; ++oItr) {
const W::Vocabulary& params = oItr->second;
if (params.has(u"filter")) {
processAddElement(lastIndex, record, oItr, sItr->first);
} else {
uint64_t bid = getInsertingNeighbour(oItr->second, record, lastIndex, getAll());
W::Address dest = oItr->first + W::Address({u"addElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(lastIndex));
if (bid != 0) {
vc->insert(u"before", new W::Uint64(bid));
}
send(vc, dest, sItr->first);
}
}
}
emit countChange(size() + 1);
return lastIndex;
}
void M::ICatalogue::removeElement(uint64_t id)
{
IndexMap::const_iterator itr = indexes.begin();
IndexMap::const_iterator end = indexes.end();
W::Vocabulary* value = getElement(id);
Map::const_iterator sItr = subscribers->begin();
Map::const_iterator sEnd = subscribers->end();
for (; sItr != sEnd; ++sItr) {
SMap::const_iterator oItr = sItr->second.begin();
SMap::const_iterator oEnd = sItr->second.end();
for (; oItr != oEnd; ++oItr) {
const W::Vocabulary& params = oItr->second;
if (params.has(u"filter")) {
const W::Vocabulary& filter = static_cast<const W::Vocabulary&>(params.at(u"filter"));
std::set<uint64_t> set = find(filter);
std::set<uint64_t>::const_iterator idItr = set.find(id);
if (idItr != set.end()) {
W::Address dest = oItr->first + W::Address({u"removeElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(id));
send(vc, dest, sItr->first);
}
} else {
W::Address dest = oItr->first + W::Address({u"removeElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(id));
send(vc, dest, sItr->first);
}
}
}
for (; itr != end; ++itr) {
itr->second->remove(value->at(itr->first), id);
}
std::map<uint64_t, M::Vocabulary*>::const_iterator aItr = activeChildren.find(id);
if (aItr != activeChildren.end()) {
removeModel(aItr->second);
aItr->second->deleteLater();
activeChildren.erase(aItr);
}
emit countChange(size() - 1);
delete value;
}
void M::ICatalogue::h_get(const W::Event& ev)
{
const W::Vocabulary& vc = static_cast<const W::Vocabulary&>(ev.getData());
const W::Vocabulary& params = static_cast<const W::Vocabulary&>(vc.at(u"params"));
std::set<uint64_t> set;
if (params.has(u"filter")) {
const W::Vocabulary& filter = static_cast<const W::Vocabulary&>(params.at(u"filter"));
set = find(filter);
} else {
set = getAll();
}
W::Vocabulary* rvc = new W::Vocabulary;
if (params.has(u"sorting")) {
const W::Vocabulary& sorting = static_cast<const W::Vocabulary&>(params.at(u"sorting"));
const W::String& field = static_cast<const W::String&>(sorting.at(u"field"));
bool ascending = static_cast<const W::Boolean&>(sorting.at(u"ascending"));
rvc->insert(u"data", indexes.at(field)->sort(set, ascending));
} else {
W::Vector* order = new W::Vector();
std::set<uint64_t>::const_iterator itr = set.begin();
std::set<uint64_t>::const_iterator end = set.end();
for (; itr != end; ++itr) {
order->push(W::Uint64(*itr));
}
rvc->insert(u"data", order);
}
response(rvc, W::Address({u"get"}), ev);
}
void M::ICatalogue::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::ICatalogue::set(const W::Object& value)
{
throw 14; //what do you expect here? not implemented, and not sure it ever would be
}
void M::ICatalogue::set(W::Object* value)
{
set(*value);
}
void M::ICatalogue::h_add(const W::Event& ev)
{
addElement(static_cast<const W::Vocabulary&>(ev.getData()));
}
void M::ICatalogue::h_update(const W::Event& ev)
{
const W::Vocabulary& data = static_cast<const W::Vocabulary&>(ev.getData());
const W::Uint64& id = static_cast<const W::Uint64&>(data.at(u"id"));
const W::Vocabulary& newValue = static_cast<const W::Vocabulary&>(data.at(u"value"));
W::Vector affectedKeys = newValue.keys();
W::Vocabulary* oldValue = getElement(id);
W::Vocabulary* modifiedValue = W::Vocabulary::extend(*oldValue, newValue);
modifyElement(id, *modifiedValue);
std::map<uint64_t, M::Vocabulary*>::const_iterator itr = activeChildren.find(id);
if (itr != activeChildren.end()) {
itr->second->set(modifiedValue);
}
Map::const_iterator sItr = subscribers->begin();
Map::const_iterator sEnd = subscribers->end();
for (; sItr != sEnd; ++sItr) {
SMap::const_iterator oItr = sItr->second.begin();
SMap::const_iterator oEnd = sItr->second.end();
for (; oItr != oEnd; ++oItr) {
const W::Vocabulary& params = oItr->second;
if (params.has(u"filter")) {
const W::Vocabulary& filter = static_cast<const W::Vocabulary&>(params.at(u"filter"));
bool matched = match(*oldValue, filter);
bool matching = match(*modifiedValue, filter);
if (matched && !matching) {
W::Address dest = oItr->first + W::Address({u"removeElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(id));
send(vc, dest, sItr->first);
} else if (!matched && matching) {
processAddElement(id, *modifiedValue, oItr, sItr->first);
} else if (matched && matching) {
std::set<uint64_t> set = find(filter);
uint64_t cbid = getInsertingNeighbour(params, *oldValue, id, set);
uint64_t bid = getInsertingNeighbour(params, *modifiedValue, id, set);
if (cbid != bid) {
W::Address dest = oItr->first + W::Address({u"moveElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(id));
if (id != 0) {
vc->insert(u"before", new W::Uint64(bid));
}
send(vc, dest, sItr->first);
}
}
} else {
if (params.has(u"sorting")) {
std::set<uint64_t> set = getAll();
uint64_t cbid = getInsertingNeighbour(params, *oldValue, id, set);
uint64_t bid = getInsertingNeighbour(params, *modifiedValue, id, set);
if (cbid != bid) {
W::Address dest = oItr->first + W::Address({u"moveElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(id));
if (id != 0) {
vc->insert(u"before", new W::Uint64(bid));
}
send(vc, dest, sItr->first);
}
}
}
}
}
}
void M::ICatalogue::h_subscribeMember(const W::Event& ev)
{
const W::Address& addr = ev.getDestination();
W::Address lastHops = addr << address.length();
if (lastHops.length() == 2 && (lastHops.ends(W::Address{u"subscribe"}) || lastHops.ends(W::Address{u"get"}))) {
W::Vocabulary* record;
try {
uint64_t id = lastHops.front().toUint64();
record = getElement(id);
if (lastHops.ends(W::Address{u"subscribe"})) {
M::Vocabulary* modelRecord = new M::Vocabulary(record, address + lastHops >> 1);
addModel(modelRecord);
activeChildren.insert(std::make_pair(id, modelRecord));
modelRecord->_h_subscribe(ev);
} else {
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", record);
fakeResponse(vc, W::Address({u"get"}), addr >> 1, ev);
}
} catch(int err) {
if (err == 3) {
emit serviceMessage(QString("An attempt to create and subscribe record model in catalogue, but it is not found. Event: ") + ev.toString().c_str());
} else {
throw err;
}
} catch (const std::invalid_argument& err) {
emit serviceMessage(QString("Strange event in custom handler of catalogue ") + ev.toString().c_str());
}
} else {
emit serviceMessage(QString("Strange event in custom handler of catalogue ") + ev.toString().c_str());
}
}
bool M::ICatalogue::match(const W::Vocabulary& value, const W::Vocabulary& filter)
{
bool m = true;
W::Vector keys = filter.keys();
for (int i = 0; i < keys.length(); ++i) {
const W::String& key = static_cast<const W::String&>(keys.at(i));
if (filter.at(key) != value.at(key)) {
m = false;
break;
};
}
return m;
}
void M::ICatalogue::processAddElement(uint64_t id, const W::Vocabulary& value, SMap::const_iterator subscriberIterator, uint64_t socketId)
{
const W::Address& addr = subscriberIterator->first;
const W::Vocabulary& params = subscriberIterator->second;
const W::Vocabulary& filter = static_cast<const W::Vocabulary&>(params.at(u"filter"));
std::set<uint64_t> set = find(filter);
std::set<uint64_t>::const_iterator idItr = set.find(id);
if (idItr != set.end()) { //to make sure if subscriber cares
uint64_t bid = getInsertingNeighbour(params, value, id, set);
W::Address dest = addr + W::Address({u"addElement"});
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"id", new W::Uint64(id));
if (id != 0) {
vc->insert(u"before", new W::Uint64(bid));
}
send(vc, dest, socketId);
}
}
uint64_t M::ICatalogue::getInsertingNeighbour(const W::Vocabulary& params, const W::Vocabulary& record, uint64_t id, const std::set<uint64_t>& allowed) const
{
uint64_t bid;
if (params.has(u"sorting")) {
if (allowed.empty()) {
bid = 0;
} else {
const W::Vocabulary& sorting = static_cast<const W::Vocabulary&>(params.at(u"sorting"));
const W::String& field = static_cast<const W::String&>(sorting.at(u"field"));
bool ascending = static_cast<const W::Boolean&>(sorting.at(u"ascending"));
uint64_t foundId = id;
do {
if (ascending) {
foundId = indexes.at(field)->getNext(foundId, record.at(field));
} else {
foundId = indexes.at(field)->getPrev(foundId, record.at(field));
}
} while (allowed.find(foundId) == allowed.end() || foundId != 0); //to make sure, that id folowing the inserting also present in the
bid = foundId; //subscribers filter result
}
} else {
std::set<uint64_t>::const_iterator idItr = allowed.find(id);
if (idItr == allowed.end()) {
bid = 0;
} else {
++idItr;
if (idItr == allowed.end()) {
bid = 0;
} else {
bid = *idItr;
}
}
}
return bid;
}
M::ICatalogue::AbstractIndex::TypeError::TypeError(const std::string& name, const std::string& method, W::Object::objectType myType, W::Object::objectType valueType):
Utils::Exception(),
name(name),
method(method),
myType(myType),
valueType(valueType)
{}
std::string M::ICatalogue::AbstractIndex::TypeError::getMessage() const
{
std::string msg = "An attempt to call Catalogue Index of ";
msg += name;
msg += " method \"";
msg += method;
msg += "\" with value type of ";
msg += W::Object::getTypeName(valueType);
msg += " but this index values supposed to have type ";
msg += W::Object::getTypeName(myType);
return msg;
}

316
lib/wModel/icatalogue.h Normal file
View file

@ -0,0 +1,316 @@
#ifndef ICATALOGUE_H
#define ICATALOGUE_H
#include "model.h"
#include <set>
#include <map>
#include <wModel/vocabulary.h>
#include <utils/exception.h>
namespace M {
class ICatalogue : public M::Model
{
Q_OBJECT
protected:
class AbstractIndex;
public:
ICatalogue(const W::Address p_address, QObject* parent = 0);
~ICatalogue();
virtual uint64_t addElement(const W::Vocabulary& record);
virtual void removeElement(uint64_t id);
virtual W::Vocabulary* getElement(uint64_t id) = 0;
virtual void modifyElement(uint64_t id, const W::Vocabulary& newValue) = 0;
virtual uint64_t size() const = 0;
virtual void clear();
virtual void addIndex(const W::String& fieldName, W::Object::objectType fieldType);
const std::set<uint64_t>& find(const W::String& indexName, const W::Object& value) const;
std::set<uint64_t> find(const W::Vocabulary& value) const;
M::Model::ModelType getType() const override;
static const M::Model::ModelType type = catalogue;
void set(const W::Object & value) override;
void set(W::Object * value) override;
W::Handler* subscribeMember;
handler(subscribeMember);
static bool match(const W::Vocabulary& value, const W::Vocabulary& filter);
static const std::set<uint64_t> empty;
signals:
void countChange(uint64_t count);
protected:
virtual std::set<uint64_t> getAll() const = 0;
void h_subscribe(const W::Event & ev) override;
handler(get);
handler(add);
handler(update);
typedef std::map<W::String, AbstractIndex*> IndexMap;
IndexMap indexes;
private:
uint64_t lastIndex;
std::map<uint64_t, M::Vocabulary*> activeChildren;
void processAddElement(uint64_t id, const W::Vocabulary& value, SMap::const_iterator subscriberIterator, uint64_t socketId);
uint64_t getInsertingNeighbour(const W::Vocabulary& params, const W::Vocabulary& record, uint64_t id, const std::set<uint64_t>& allowed = empty) const;
protected:
class AbstractIndex {
public:
AbstractIndex(W::Object::objectType vt): valueType(vt) {}
virtual ~AbstractIndex() {}
virtual const std::set<uint64_t>& find(const W::Object& value) const = 0;
virtual void add(const W::Object& value, uint64_t id) = 0;
virtual void remove(const W::Object & value, uint64_t id) = 0;
virtual void clear() = 0;
virtual W::Vector sort(const std::set<uint64_t>& set, bool ascending) = 0;
virtual uint64_t getNext(uint64_t id, const W::Object& value) = 0;
virtual uint64_t getPrev(uint64_t id, const W::Object& value) = 0;
W::Object::objectType valueType;
protected:
class TypeError : public Utils::Exception {
public:
TypeError(const std::string& name, const std::string& method, W::Object::objectType myType, W::Object::objectType valueType);
std::string getMessage() const;
private:
std::string name;
std::string method;
W::Object::objectType myType;
W::Object::objectType valueType;
};
};
template <class T>
class Index : public AbstractIndex {
public:
Index();
~Index();
const std::set<uint64_t>& find(const W::Object& value) const override;
void add(const W::Object & value, uint64_t id) override;
void remove(const W::Object & value, uint64_t id) override;
void clear() override;
W::Vector sort(const std::set<uint64_t> & set, bool ascending) override;
uint64_t getNext(uint64_t id, const W::Object& value) override;
uint64_t getPrev(uint64_t id, const W::Object& value) override;
private:
typedef std::map<T, std::set<uint64_t>> Map;
Map values;
};
};
template<class T>
ICatalogue::Index<T>::Index():
ICatalogue::AbstractIndex(T::type),
values()
{
}
template<class T>
ICatalogue::Index<T>::~Index()
{
}
template<class T>
const std::set<uint64_t> & ICatalogue::Index<T>::find(const W::Object& value) const
{
if (value.getType() != valueType) {
throw new TypeError("Unknown", "find", valueType, value.getType()); //todo replace that unknown stuff, find a way to provide index name
}
const T& val = static_cast<const T&>(value);
typename std::map<T, std::set<uint64_t>>::const_iterator itr = values.find(val);
if (itr == values.end()) {
return ICatalogue::empty;
} else {
return itr->second;
}
}
template<class T>
void ICatalogue::Index<T>::add(const W::Object& value, uint64_t id)
{
if (value.getType() != valueType) {
throw new TypeError("Unknown", "add", valueType, value.getType());
}
const T& val = static_cast<const T&>(value);
typename std::map<T, std::set<uint64_t>>::iterator itr = values.find(val);
if (itr == values.end()) {
itr = values.insert(std::make_pair(val, std::set<uint64_t>())).first;
}
itr->second.insert(id);
}
template<class T>
void ICatalogue::Index<T>::remove(const W::Object& value, uint64_t id)
{
if (value.getType() != valueType) {
throw new TypeError("Unknown", "remove", valueType, value.getType());
}
const T& val = static_cast<const T&>(value);
typename std::map<T, std::set<uint64_t>>::iterator itr = values.find(val);
if (itr != values.end()) {
std::set<uint64_t>& set = itr->second;
if (set.size() == 1) {
values.erase(itr);
} else {
std::set<uint64_t>::const_iterator hint = set.find(id);
set.erase(hint);
}
}
}
template<class T>
void ICatalogue::Index<T>::clear()
{
values.clear();
}
template<class T>
W::Vector ICatalogue::Index<T>::sort(const std::set<uint64_t> & set, bool ascending) //TODO this needs an optimization
{
W::Vector res;
std::set<uint64_t>::const_iterator sEnd = set.end();
uint64_t size = set.size();
if (size == 0) {
return res;
} else if (size == 1) {
res.push(W::Uint64(*(set.begin())));
return res;
}
if (ascending) {
typename std::map<T, std::set<uint64_t>>::const_iterator itr = values.begin();
typename std::map<T, std::set<uint64_t>>::const_iterator end = values.end();
for (; itr != end; ++itr) {
if (size == res.size()) {
break;
}
const std::set<uint64_t>& chunk = itr->second;
std::set<uint64_t>::const_iterator cItr = chunk.begin();
std::set<uint64_t>::const_iterator cEnd = chunk.end();
for (; cItr != cEnd; ++cItr) {
uint64_t id = *cItr;
if (set.find(id) != sEnd) {
res.push(W::Uint64(id));
}
}
}
} else {
typename std::map<T, std::set<uint64_t>>::reverse_iterator itr = values.rbegin();
typename std::map<T, std::set<uint64_t>>::reverse_iterator end = values.rend();
for (; itr != end; ++itr) {
if (size == res.size()) {
break;
}
const std::set<uint64_t>& chunk = itr->second;
std::set<uint64_t>::const_iterator cItr = chunk.begin();
std::set<uint64_t>::const_iterator cEnd = chunk.end();
for (; cItr != cEnd; ++cItr) {
uint64_t id = *cItr;
if (set.find(id) != sEnd) {
res.push(W::Uint64(id));
}
}
}
}
return res;
}
template<class T>
uint64_t ICatalogue::Index<T>::getNext(uint64_t id, const W::Object& value)
{
if (value.getType() != valueType) {
throw new TypeError("Unknown", "getNext", valueType, value.getType());
}
const T& val = static_cast<const T&>(value);
typename std::map<T, std::set<uint64_t>>::iterator itr = values.find(val);
if (itr == values.end()) {
throw 2; //this is not suppose to happen!
}
const std::set<uint64_t>& set = itr->second;
std::set<uint64_t>::const_iterator sItr = set.find(id);
if (sItr == set.end()) {
throw 2; //not suppose to happen!
}
++sItr;
if (sItr == set.end()) {
++itr;
bool found = false;
while (itr != values.end()) {
if (itr->second.size() != 0) {
sItr = set.begin();
found = true;
break;
}
++itr;
}
if (!found) {
return 0;
}
}
return *sItr;
}
template<class T>
uint64_t ICatalogue::Index<T>::getPrev(uint64_t id, const W::Object& value)
{
if (value.getType() != valueType) {
throw new TypeError("Unknown", "getPrev", valueType, value.getType());
}
const T& val = static_cast<const T&>(value);
typename std::map<T, std::set<uint64_t>>::iterator itr = values.find(val);
if (itr == values.end()) {
throw 2; //this is not suppose to happen!
}
const std::set<uint64_t>& set = itr->second;
std::set<uint64_t>::const_iterator sItr = set.find(id);
if (sItr == set.end()) {
throw 2; //not suppose to happen!
}
if (sItr == set.begin()) {
bool found = false;
while (itr != values.begin()) {
--itr;
if (itr->second.size() != 0) {
sItr = set.end();
--sItr;
break;
}
}
if (!found) {
return 0;
}
} else {
--sItr;
}
return *sItr;
}
}
#endif // ICATALOGUE_H

100
lib/wModel/list.cpp Normal file
View file

@ -0,0 +1,100 @@
#include "list.h"
M::List::List(const W::Address p_address, QObject* parent):
M::Model(p_address, parent),
data(new W::Vector())
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::List::_h_get);
addHandler(get);
}
M::List::~List()
{
delete data;
}
void M::List::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::List::h_get(const W::Event& ev)
{
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", data->copy());
response(vc, W::Address({u"get"}), ev);
}
void M::List::push(const W::Object& obj)
{
data->push(obj);
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"data", obj);
broadcast(vc, W::Address{u"push"});
}
}
void M::List::push(W::Object* obj)
{
data->push(obj);
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"data", obj->copy());
broadcast(vc, W::Address{u"push"});
}
}
void M::List::clear()
{
data->clear();
if (registered) {
broadcast(new W::Vocabulary(), W::Address{u"clear"});
}
}
M::Model::ModelType M::List::getType() const
{
return type;
}
void M::List::set(const W::Object& value)
{
delete data;
data = static_cast<W::Vector*>(value.copy());
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", data->copy());
broadcast(vc, W::Address({u"get"}));
}
void M::List::set(W::Object* value)
{
delete data;
data = static_cast<W::Vector*>(value);
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", data->copy());
broadcast(vc, W::Address({u"get"}));
}
uint64_t M::List::size() const
{
return data->size();
}
const W::Object & M::List::at(uint64_t index) const
{
return data->at(index);
}

41
lib/wModel/list.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef M_LIST_H
#define M_LIST_H
#include "model.h"
#include <wType/object.h>
#include <wType/address.h>
#include <wType/vector.h>
namespace M {
class List : public M::Model
{
public:
List(const W::Address p_address, QObject* parent = 0);
~List();
void push(const W::Object& obj);
void push(W::Object* obj);
void clear();
uint64_t size() const;
const W::Object& at(uint64_t index) const;
void set(const W::Object & value) override;
void set(W::Object * value) override;
M::Model::ModelType getType() const override;
static const M::Model::ModelType type = list;
protected:
void h_subscribe(const W::Event & ev) override;
handler(get);
private:
W::Vector* data;
};
}
#endif // M_LIST_H

339
lib/wModel/model.cpp Normal file
View file

@ -0,0 +1,339 @@
#include "model.h"
M::Model::Model(const W::Address p_address, QObject* parent):
QObject(parent),
address(p_address),
registered(false),
subscribers(new Map()),
dispatcher(0),
server(0),
subscribersCount(0),
handlers(new HList()),
properties(new W::Vector()),
models(new MList())
{
W::Handler* subscribe = W::Handler::create(address + W::Address({u"subscribe"}), this, &M::Model::_h_subscribe);
W::Handler* unsubscribe = W::Handler::create(address + W::Address({u"unsubscribe"}), this, &M::Model::_h_unsubscribe);
addHandler(subscribe);
addHandler(unsubscribe);
}
M::Model::~Model()
{
if (registered) {
unregisterModel();
}
MList::iterator itr = models->begin();
MList::iterator end = models->end();
for (; itr != end; ++itr) {
delete *itr;
}
HList::iterator hItr = handlers->begin();
HList::iterator hEnd = handlers->end();
for (; hItr != hEnd; ++hItr) {
delete *hItr;
}
delete subscribers;
delete properties;
delete handlers;
delete models;
}
void M::Model::addModel(M::Model* model)
{
models->push_back(model);
connect(model, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
if (registered) {
model->registerModel(dispatcher, server);
}
}
void M::Model::addHandler(W::Handler* handler)
{
handlers->push_back(handler);
if (registered) {
dispatcher->registerHandler(handler);
}
}
void M::Model::addProperty(const W::String& value, const W::String& name)
{
W::Vocabulary vc;
vc.insert(u"key", name);
vc.insert(u"property", value);
properties->push(vc);
if (registered) {
W::Vocabulary* nvc = new W::Vocabulary;
nvc->insert(u"properties", *properties);
broadcast(nvc, W::Address({u"properties"}));
}
}
W::Address M::Model::getAddress() const
{
return address;
}
void M::Model::registerModel(W::Dispatcher* dp, W::Server* srv)
{
if (registered) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + " is already registered");
throw 1;
} else {
dispatcher = dp;
server = srv;
MList::iterator itr = models->begin();
MList::iterator end = models->end();
for (; itr != end; ++itr) {
M::Model* model = *itr;
model->registerModel(dispatcher, server);
}
HList::iterator hItr = handlers->begin();
HList::iterator hEnd = handlers->end();
for (; hItr != hEnd; ++hItr) {
W::Handler* handler = *hItr;
dispatcher->registerHandler(handler);
}
registered = true;
}
}
void M::Model::unregisterModel()
{
if (!registered) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + " is not registered");
throw 2;
} else {
MList::iterator itr = models->begin();
MList::iterator end = models->end();
for (; itr != end; ++itr) {
Model* model = *itr;
model->unregisterModel();
}
HList::iterator hItr = handlers->begin();
HList::iterator hEnd = handlers->end();
for (; hItr != hEnd; ++hItr) {
W::Handler* handler = *hItr;
dispatcher->unregisterHandler(handler);
}
Map::iterator sItr = subscribers->begin();
Map::iterator sEnd = subscribers->end();
for (; sItr != sEnd; ++sItr) {
const W::Socket& socket = server->getConnection(sItr->first);
disconnect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
}
subscribers->clear();
subscribersCount = 0;
dispatcher = 0;
server = 0;
registered = false;
}
}
void M::Model::h_subscribe(const W::Event& ev)
{
uint64_t id = ev.getSenderId();
const W::Vocabulary& vc = static_cast<const W::Vocabulary&>(ev.getData());
const W::Address& source = static_cast<const W::Address&>(vc.at(u"source"));
W::Vocabulary params;
if (vc.has(u"params")) {
params = static_cast<const W::Vocabulary&>(vc.at(u"params"));
}
Map::iterator sItr = subscribers->find(id);
if (sItr == subscribers->end()) {
std::pair<Map::iterator, bool> pair = subscribers->emplace(std::make_pair(id, SMap()));
if (!pair.second) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + ": something completely wrong happened");
throw 3;
}
const W::Socket& socket = server->getConnection(id);
connect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
sItr = pair.first;
}
SMap::const_iterator oItr = sItr->second.find(source);
if (oItr != sItr->second.end()) {
emit serviceMessage(QString("Socket ") + id +
" subscriber " + source.toString().c_str() +
" is already subscribed to model " + source.toString().c_str());
throw 4;
}
sItr->second.insert(std::make_pair(source, params));
++subscribersCount;
W::Vocabulary* nvc = new W::Vocabulary();
nvc->insert(u"properties", *properties);
response(nvc, W::Address({u"properties"}), ev);
emit serviceMessage(QString("Model ") + address.toString().c_str() + ": now has " + std::to_string(subscribersCount).c_str() + " subscribers");
emit subscribersCountChange(subscribersCount);
}
void M::Model::onSocketDisconnected()
{
W::Socket* socket = static_cast<W::Socket*>(sender());
disconnect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
uint64_t id = socket->getId();
Map::iterator itr = subscribers->find(id);
if (itr == subscribers->end()) {
emit serviceMessage(QString("Model ") + address.toString().c_str() +
": socket disconnected have been handled for not subscribed id");
throw 5;
}
subscribersCount -= itr->second.size();
subscribers->erase(itr);
emit serviceMessage(QString("Model ") + address.toString().c_str() + ": now has " + std::to_string(subscribersCount).c_str() + " subscribers");
emit subscribersCountChange(subscribersCount);
}
void M::Model::h_unsubscribe(const W::Event& ev)
{
uint64_t id = ev.getSenderId();
const W::Vocabulary& vc = static_cast<const W::Vocabulary&>(ev.getData());
const W::Address& source = static_cast<const W::Address&>(vc.at(u"source"));
Map::iterator itr = subscribers->find(id);
if (itr == subscribers->end()) {
emit serviceMessage(QString("Socket ") + id +
" has no subscribed addresses to model " + source.toString().c_str());
throw 6;
}
SMap& smap = itr->second;
SMap::const_iterator sItr = smap.find(source);
if (sItr == smap.end()) {
emit serviceMessage(QString("Socket ") + id +
" subscriber " + source.toString().c_str() +
" is not subscribed to model " + source.toString().c_str());
throw 7;
}
smap.erase(sItr);
if (smap.size() == 0) {
const W::Socket& socket = server->getConnection(itr->first);
disconnect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
subscribers->erase(itr);
}
--subscribersCount;
emit serviceMessage(QString("Model ") + address.toString().c_str() + ": now has " + std::to_string(subscribersCount).c_str() + " subscribers");
emit subscribersCountChange(subscribersCount);
}
void M::Model::send(W::Vocabulary* vc, const W::Address& destination, uint64_t connectionId)
{
if (!registered) {
emit serviceMessage(QString("An attempt to send event from model ") + address.toString().c_str() + " which was not registered");
throw 8;
}
W::Event ev(destination, vc);
ev.setSenderId(connectionId);
server->getConnection(connectionId).send(ev);
}
void M::Model::response(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Event& src)
{
if (!registered) {
emit serviceMessage(QString("An attempt to send event from model ") + address.toString().c_str() + " which was not registered");
throw 8;
}
const W::Vocabulary& svc = static_cast<const W::Vocabulary&>(src.getData());
const W::Address& source = static_cast<const W::Address&>(svc.at(u"source"));
uint64_t id = src.getSenderId();
vc->insert(u"source", address);
W::Event ev(source + handlerAddress, vc);
ev.setSenderId(id);
server->getConnection(id).send(ev);
}
void M::Model::fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Address& sourceAddress, const W::Event& src)
{
if (!registered) {
emit serviceMessage(QString("An attempt to send event from model ") + address.toString().c_str() + " which was not registered");
throw 8;
}
const W::Vocabulary& svc = static_cast<const W::Vocabulary&>(src.getData());
const W::Address& source = static_cast<const W::Address&>(svc.at(u"source"));
uint64_t id = src.getSenderId();
vc->insert(u"source", sourceAddress);
W::Event ev(source + handlerAddress, vc);
ev.setSenderId(id);
server->getConnection(id).send(ev);
}
void M::Model::broadcast(W::Vocabulary* vc, const W::Address& handlerAddress)
{
if (!registered) {
emit serviceMessage(QString("An attempt to send event from model ") + address.toString().c_str() + " which was not registered");
throw 8;
}
Map::const_iterator itr = subscribers->begin();
Map::const_iterator end = subscribers->end();
vc->insert(u"source", address);
for (;itr != end; ++itr) {
SMap::const_iterator oItr = itr->second.begin();
SMap::const_iterator oEnd = itr->second.end();
for (;oItr != oEnd; ++oItr) {
W::Event ev(oItr->first + handlerAddress, vc->copy());
ev.setSenderId(itr->first);
server->getConnection(itr->first).send(ev);
}
}
delete vc;
}
void M::Model::removeHandler(W::Handler* handler)
{
handlers->erase(handler);
if (registered) {
dispatcher->unregisterHandler(handler);
}
}
void M::Model::removeModel(M::Model* model)
{
models->erase(model);
if (registered) {
model->unregisterModel();
}
}
void M::Model::passToHandler(const W::Event& event) const
{
if (registered) {
dispatcher->pass(event);
} else {
emit serviceMessage(QString("An attempt to pass event to dispatcher from unregistered model\nModel address ") + address.toString().c_str());
}
}

92
lib/wModel/model.h Normal file
View file

@ -0,0 +1,92 @@
#ifndef W_MODEL_H
#define W_MODEL_H
#include <utils/defines.h>
#include <map>
#include <list>
#include <QtCore/QObject>
#include <QtCore/QString>
#include <wType/address.h>
#include <wType/vector.h>
#include <wType/event.h>
#include <wType/string.h>
#include <wSocket/socket.h>
#include <wSocket/server.h>
#include <wDispatcher/dispatcher.h>
#include <wDispatcher/handler.h>
#include <wContainer/order.h>
namespace M {
class Model : public QObject
{
Q_OBJECT
public:
enum ModelType {
string,
list,
vocabulary,
catalogue,
attributes = 50,
file,
resourceCache
};
Model(const W::Address p_address, QObject* parent = 0);
//i'm not sure about copy constructor, it just doesn't make sense, because the address is the parameter which is supposed to be unique
virtual ~Model();
virtual ModelType getType() const = 0;
virtual void set(W::Object* value) = 0;
virtual void set(const W::Object& value) = 0;
void addModel(M::Model* model);
void addHandler(W::Handler* handler);
void addProperty(const W::String& value, const W::String& name);
W::Address getAddress() const;
void registerModel(W::Dispatcher* dp, W::Server* srv);
void unregisterModel();
void removeHandler(W::Handler* handler);
void removeModel(M::Model* model);
void passToHandler(const W::Event& event) const;
signals:
void serviceMessage(const QString& msg) const;
void subscribersCountChange(uint64_t count) const;
protected:
typedef std::map<W::Address, W::Vocabulary> SMap;
typedef std::map<uint64_t, SMap> Map;
W::Address address;
bool registered;
Map* subscribers;
void send(W::Vocabulary* vc, const W::Address& destination, uint64_t connectionId);
void response(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Event& src);
void fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Address& sourceAddress, const W::Event& src);
void broadcast(W::Vocabulary* vc, const W::Address& handlerAddress);
handler(subscribe)
handler(unsubscribe)
private:
typedef W::Order<W::Handler*> HList;
typedef W::Order<M::Model*> MList;
W::Dispatcher* dispatcher;
W::Server* server;
uint64_t subscribersCount;
HList* handlers;
W::Vector* properties;
MList* models;
private slots:
void onSocketDisconnected();
};
}
#endif // W_MODEL_H

View file

@ -0,0 +1,77 @@
#include "modelstring.h"
M::String::String(const W::String& str, const W::Address& addr, QObject* parent):
M::Model(addr, parent),
data(new W::String(str))
{
addHandler(W::Handler::create(address + W::Address({u"get"}), this, &M::String::_h_get));
}
M::String::String(W::String* str, const W::Address& addr, QObject* parent):
M::Model(addr, parent),
data(str)
{
}
M::String::~String()
{
delete data;
}
void M::String::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::String::h_get(const W::Event& ev)
{
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", *data);
response(vc, W::Address({u"get"}), ev);
}
void M::String::set(const W::String& str)
{
delete data;
data = static_cast<W::String*>(str.copy());
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"data", str);
broadcast(vc, W::Address{u"get"});
}
}
void M::String::set(W::String* str)
{
delete data;
data = str;
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"data", *str);
broadcast(vc, W::Address{u"get"});
}
}
void M::String::set(const W::Object& value)
{
set(static_cast<const W::String&>(value));
}
void M::String::set(W::Object* value)
{
set(static_cast<W::String*>(value));
}
M::Model::ModelType M::String::getType() const
{
return type;
}

40
lib/wModel/modelstring.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef M_STRING_H
#define M_STRING_H
#include "model.h"
#include <QtCore/QObject>
#include <wType/string.h>
#include <wType/address.h>
namespace M {
class String: public Model
{
public:
String(const W::String& str, const W::Address& addr, QObject* parent = 0);
String(W::String* str, const W::Address& addr, QObject* parent = 0);
~String();
void set(const W::Object & value) override;
void set(W::Object * value) override;
void set(const W::String& str);
void set(W::String* str);
M::Model::ModelType getType() const override;
static const M::Model::ModelType type = M::Model::string;
protected:
void h_subscribe(const W::Event& ev);
handler(get)
private:
W::String* data;
};
}
#endif // M_STRING_H

136
lib/wModel/vocabulary.cpp Normal file
View file

@ -0,0 +1,136 @@
#include "vocabulary.h"
M::Vocabulary::Vocabulary(const W::Address p_address, QObject* parent):
M::Model(p_address, parent),
data(new W::Vocabulary())
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::Vocabulary::_h_get);
addHandler(get);
}
M::Vocabulary::Vocabulary(W::Vocabulary* p_data, const W::Address p_address, QObject* parent):
M::Model(p_address, parent),
data(p_data)
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::Vocabulary::_h_get);
addHandler(get);
}
M::Vocabulary::~Vocabulary()
{
delete data;
}
void M::Vocabulary::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::Vocabulary::h_get(const W::Event& ev)
{
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", data->copy());
response(vc, W::Address({u"get"}), ev);
}
void M::Vocabulary::insert(const W::String& key, const W::Object& value)
{
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
W::Vocabulary* insert = new W::Vocabulary();
W::Vector* erase = new W::Vector();
if (data->has(key)) {
erase->push(key);
}
data->insert(key, value);
insert->insert(key, value);
vc->insert(u"insert", insert);
vc->insert(u"erase", erase);
broadcast(vc, W::Address{u"change"});
} else {
data->insert(key, value);
}
}
void M::Vocabulary::insert(const W::String& key, W::Object* value)
{
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
W::Vocabulary* insert = new W::Vocabulary();
W::Vector* erase = new W::Vector();
if (data->has(key)) {
erase->push(key);
}
data->insert(key, value);
insert->insert(key, value->copy());
vc->insert(u"insert", insert);
vc->insert(u"erase", erase);
broadcast(vc, W::Address{u"change"});
} else {
data->insert(key, value);
}
}
void M::Vocabulary::erase(const W::String& key)
{
data->erase(key);
if (registered) {
W::Vocabulary* vc = new W::Vocabulary();
W::Vocabulary* insert = new W::Vocabulary();
W::Vector* erase = new W::Vector();
erase->push(key);
vc->insert(u"insert", insert);
vc->insert(u"erase", erase);
broadcast(vc, W::Address{u"change"});
}
}
void M::Vocabulary::clear()
{
data->clear();
if (registered) {
broadcast(new W::Vocabulary(), W::Address{u"clear"});
}
}
M::Model::ModelType M::Vocabulary::getType() const
{
return type;
}
void M::Vocabulary::set(const W::Object& value)
{
delete data;
data = static_cast<W::Vocabulary*>(value.copy());
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", data->copy());
broadcast(vc, W::Address({u"get"}));
}
void M::Vocabulary::set(W::Object* value)
{
delete data;
data = static_cast<W::Vocabulary*>(value);
W::Vocabulary* vc = new W::Vocabulary;
vc->insert(u"data", data->copy());
broadcast(vc, W::Address({u"get"}));
}

45
lib/wModel/vocabulary.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef M_VOCABULARY_H
#define M_VOCABULARY_H
#include "model.h"
#include <wType/object.h>
#include <wType/address.h>
#include <wType/vocabulary.h>
#include <wType/vector.h>
namespace M {
class ICatalogue;
class Vocabulary : public M::Model
{
friend class ICatalogue;
public:
Vocabulary(const W::Address p_address, QObject* parent = 0);
Vocabulary(W::Vocabulary* p_data, const W::Address p_address, QObject* parent = 0);
~Vocabulary();
void insert(const W::String& key, const W::Object& value);
void insert(const W::String& key, W::Object* value);
void erase(const W::String& key);
void clear();
void set(const W::Object & value) override;
void set(W::Object* value) override;
M::Model::ModelType getType() const override;
static const M::Model::ModelType type = vocabulary;
protected:
void h_subscribe(const W::Event & ev) override;
handler(get);
private:
W::Vocabulary* data;
};
}
#endif // M_VOCABULARY_H