diff --git a/src/core/serverMasterController/data/data-decorator.cpp b/src/core/serverMasterController/data/data-decorator.cpp new file mode 100644 index 000000000..5c0dab007 --- /dev/null +++ b/src/core/serverMasterController/data/data-decorator.cpp @@ -0,0 +1,45 @@ +#include "data-decorator.h" + +namespace cm { +namespace data { + +class DataDecorator::Implementation +{ +public: + Implementation(Entity* _parent, const QString& _key, const QString& _label) + : parentEntity(_parent) + , key(_key) + , label(_label) + { + } + Entity* parentEntity{nullptr}; + QString key; + QString label; +}; + +DataDecorator::DataDecorator(Entity* parent, const QString& key, const QString& label) + : QObject((QObject*)parent) +{ + implementation.reset(new Implementation(parent, key, label)); +} + +DataDecorator::~DataDecorator() +{ +} + +const QString& DataDecorator::key() const +{ + return implementation->key; +} + +const QString& DataDecorator::label() const +{ + return implementation->label; +} + +Entity* DataDecorator::parentEntity() +{ + return implementation->parentEntity; +} + +}} diff --git a/src/core/serverMasterController/data/data-decorator.h b/src/core/serverMasterController/data/data-decorator.h new file mode 100644 index 000000000..b606c5c98 --- /dev/null +++ b/src/core/serverMasterController/data/data-decorator.h @@ -0,0 +1,39 @@ +#ifndef DATADECORATOR_H +#define DATADECORATOR_H + +#include +#include +#include +#include + +#include + +namespace cm { +namespace data { + +class Entity; + +class CMLIBSHARED_EXPORT DataDecorator : public QObject +{ + Q_OBJECT + Q_PROPERTY( QString ui_label READ label CONSTANT ) + +public: + DataDecorator(Entity* parent = nullptr, const QString& key = "SomeItemKey", const QString& label = ""); + virtual ~DataDecorator(); + + const QString& key() const; + const QString& label() const; + Entity* parentEntity(); + + virtual QJsonValue jsonValue() const = 0; + virtual void update(const QJsonObject& jsonObject) = 0; + +private: + class Implementation; + QScopedPointer implementation; +}; + +}} + +#endif diff --git a/src/core/serverMasterController/data/datetime-decorator.cpp b/src/core/serverMasterController/data/datetime-decorator.cpp new file mode 100644 index 000000000..e25f1db86 --- /dev/null +++ b/src/core/serverMasterController/data/datetime-decorator.cpp @@ -0,0 +1,99 @@ +#include "datetime-decorator.h" + +#include + +namespace cm { +namespace data { + +class DateTimeDecorator::Implementation +{ +public: + Implementation(DateTimeDecorator* dateTimeDecorator, const QDateTime& value) + : dateTimeDecorator(dateTimeDecorator) + , value(value) + { + } + + DateTimeDecorator* dateTimeDecorator{nullptr}; + QDateTime value; +}; + +DateTimeDecorator::DateTimeDecorator(Entity* parentEntity, const QString& key, const QString& label, const QDateTime& value) + : DataDecorator(parentEntity, key, label) +{ + implementation.reset(new Implementation(this, value)); +} + +DateTimeDecorator::~DateTimeDecorator() +{ +} + +const QDateTime& DateTimeDecorator::value() const +{ + return implementation->value; +} + +DateTimeDecorator& DateTimeDecorator::setValue(const QDateTime& value) +{ + if(value != implementation->value) { + // ...Validation here if required... + implementation->value = value; + emit valueChanged(); + } + + return *this; +} + +QString DateTimeDecorator::toIso8601String() const +{ + if (implementation->value.isNull()) { + return ""; + } else { + return implementation->value.toString(Qt::ISODate); + } +} + +QString DateTimeDecorator::toPrettyString() const +{ + if (implementation->value.isNull()) { + return "Not set"; + } else { + return implementation->value.toString( "ddd d MMM yyyy @ HH:mm:ss" ); + } +} + +QString DateTimeDecorator::toPrettyDateString() const +{ + if (implementation->value.isNull()) { + return "Not set"; + } else { + return implementation->value.toString( "d MMM yyyy" ); + } +} + +QString DateTimeDecorator::toPrettyTimeString() const +{ + if (implementation->value.isNull()) { + return "Not set"; + } else { + return implementation->value.toString( "hh:mm ap" ); + } +} + +QJsonValue DateTimeDecorator::jsonValue() const +{ + return QJsonValue::fromVariant(QVariant(implementation->value.toString(Qt::ISODate))); +} + +void DateTimeDecorator::update(const QJsonObject& jsonObject) +{ + if (jsonObject.contains(key())) { + auto valueAsString = jsonObject.value(key()).toString(); + auto valueAsDate = QDateTime::fromString(valueAsString, Qt::ISODate); // yyyy-MM-ddTHH:mm:ss + setValue(valueAsDate); + } else { + setValue(QDateTime()); + } +} + +}} diff --git a/src/core/serverMasterController/data/datetime-decorator.h b/src/core/serverMasterController/data/datetime-decorator.h new file mode 100644 index 000000000..b20190cb2 --- /dev/null +++ b/src/core/serverMasterController/data/datetime-decorator.h @@ -0,0 +1,49 @@ +#ifndef DATETIMEDECORATOR_H +#define DATETIMEDECORATOR_H + +#include +#include +#include +#include +#include + +#include +#include + +namespace cm { +namespace data { + +class CMLIBSHARED_EXPORT DateTimeDecorator : public DataDecorator +{ + Q_OBJECT + Q_PROPERTY( QString ui_iso8601String READ toIso8601String NOTIFY valueChanged ) + Q_PROPERTY( QString ui_prettyDateString READ toPrettyDateString NOTIFY valueChanged ) + Q_PROPERTY( QString ui_prettyTimeString READ toPrettyTimeString NOTIFY valueChanged ) + Q_PROPERTY( QString ui_prettyString READ toPrettyString NOTIFY valueChanged ) + Q_PROPERTY( QDateTime ui_value READ value WRITE setValue NOTIFY valueChanged ) + +public: + DateTimeDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", const QDateTime& value = QDateTime()); + ~DateTimeDecorator(); + + const QDateTime& value() const; + DateTimeDecorator& setValue(const QDateTime& value); + QString toIso8601String() const; + QString toPrettyDateString() const; + QString toPrettyTimeString() const; + QString toPrettyString() const; + + QJsonValue jsonValue() const override; + void update(const QJsonObject& jsonObject) override; + +signals: + void valueChanged(); + +private: + class Implementation; + QScopedPointer implementation; +}; + +}} + +#endif diff --git a/src/core/serverMasterController/data/entity-collection.h b/src/core/serverMasterController/data/entity-collection.h new file mode 100644 index 000000000..ff4b26e1a --- /dev/null +++ b/src/core/serverMasterController/data/entity-collection.h @@ -0,0 +1,125 @@ +#ifndef ENTITYCOLLECTION_H +#define ENTITYCOLLECTION_H + +#include +#include +#include + +#include + +namespace cm { +namespace data { + +class Entity; + +class CMLIBSHARED_EXPORT EntityCollectionObject : public QObject +{ + Q_OBJECT + +public: + EntityCollectionObject(QObject* _parent = nullptr) : QObject(_parent) {} + virtual ~EntityCollectionObject() {} + +signals: + void collectionChanged(); +}; + +class EntityCollectionBase : public EntityCollectionObject +{ +public: + EntityCollectionBase(QObject* parent = nullptr, const QString& key = "SomeCollectionKey") + : EntityCollectionObject(parent) + , key(key) + {} + + virtual ~EntityCollectionBase() + {} + + QString getKey() const + { + return key; + } + + virtual void clear() = 0; + virtual void update(const QJsonArray& json) = 0; + virtual std::vector baseEntities() = 0; + + template + QList& derivedEntities(); + + template + T* addEntity(T* entity); + +private: + QString key; +}; + +template +class EntityCollection : public EntityCollectionBase +{ +public: + EntityCollection(QObject* parent = nullptr, const QString& key = "SomeCollectionKey") + : EntityCollectionBase(parent, key) + {} + + ~EntityCollection() + {} + + void clear() override + { + for(auto entity : collection) { + entity->deleteLater(); + } + collection.clear(); + } + + void update(const QJsonArray& jsonArray) override + { + clear(); + for(const QJsonValue& jsonValue : jsonArray) { + addEntity(new T(this, jsonValue.toObject())); + } + } + + std::vector baseEntities() override + { + std::vector returnValue; + for(T* entity : collection) { + returnValue.push_back(entity); + } + return returnValue; + } + + QList& derivedEntities() + { + return collection; + } + + T* addEntity(T* entity) + { + if(!collection.contains(entity)) { + collection.append(entity); + EntityCollectionObject::collectionChanged(); + } + return entity; + } + +private: + QList collection; +}; + +template +QList& EntityCollectionBase::derivedEntities() +{ + return dynamic_cast&>(*this).derivedEntities(); +} + +template +T* EntityCollectionBase::addEntity(T* entity) +{ + return dynamic_cast&>(*this).addEntity(entity); +} + +}} + +#endif diff --git a/src/core/serverMasterController/data/entity.cpp b/src/core/serverMasterController/data/entity.cpp new file mode 100644 index 000000000..5acf1f059 --- /dev/null +++ b/src/core/serverMasterController/data/entity.cpp @@ -0,0 +1,117 @@ +#include "entity.h" + +#include + +namespace cm { +namespace data { + +class Entity::Implementation +{ +public: + Implementation(Entity* _entity, const QString& _key) + : entity(_entity) + , key(_key) + { + } + Entity* entity{nullptr}; + QString key; + std::map childCollections; + std::map childEntities; + std::map dataDecorators; +}; + +Entity::Entity(QObject* parent, const QString& key) + : QObject(parent) +{ + implementation.reset(new Implementation(this, key)); +} + +Entity::Entity(QObject* parent, const QString& key, const QJsonObject& jsonObject) + : Entity(parent, key) +{ + update(jsonObject); +} + +Entity::~Entity() +{ +} +const QString& Entity::key() const +{ + return implementation->key; +} + +Entity* Entity::addChild(Entity* entity, const QString& key) +{ + if(implementation->childEntities.find(key) == std::end(implementation->childEntities)) { + implementation->childEntities[key] = entity; + emit childEntitiesChanged(); + } + + return entity; +} + +EntityCollectionBase* Entity::addChildCollection(EntityCollectionBase* entityCollection) +{ + if(implementation->childCollections.find(entityCollection->getKey()) == std::end(implementation->childCollections)) { + implementation->childCollections[entityCollection->getKey()] = entityCollection; + emit childCollectionsChanged(entityCollection->getKey()); + } + + return entityCollection; +} + +DataDecorator* Entity::addDataItem(DataDecorator* dataDecorator) +{ + if(implementation->dataDecorators.find(dataDecorator->key()) == std::end(implementation->dataDecorators)) { + implementation->dataDecorators[dataDecorator->key()] = dataDecorator; + emit dataDecoratorsChanged(); + } + + return dataDecorator; +} + +void Entity::update(const QJsonObject& jsonObject) +{ + // Update data decorators + for (std::pair dataDecoratorPair : implementation->dataDecorators) { + dataDecoratorPair.second->update(jsonObject); + } + + // Update child entities + for (std::pair childEntityPair : implementation->childEntities) { + childEntityPair.second->update(jsonObject.value(childEntityPair.first).toObject()); + } + + // Update child collections + for (std::pair childCollectionPair : implementation->childCollections) { + childCollectionPair.second->update(jsonObject.value(childCollectionPair.first).toArray()); + } +} + +QJsonObject Entity::toJson() const +{ + QJsonObject returnValue; + + // Add data decorators + for (std::pair dataDecoratorPair : implementation->dataDecorators) { + returnValue.insert( dataDecoratorPair.first, dataDecoratorPair.second->jsonValue() ); + } + + // Add child entities + for (std::pair childEntityPair : implementation->childEntities) { + returnValue.insert( childEntityPair.first, childEntityPair.second->toJson() ); + } + + // Add child collections + for (std::pair childCollectionPair : implementation->childCollections) { + QJsonArray entityArray; + for (Entity* entity : childCollectionPair.second->baseEntities()) { + entityArray.append( entity->toJson() ); + } + returnValue.insert( childCollectionPair.first, entityArray ); + } + + return returnValue; +} + +}} diff --git a/src/core/serverMasterController/data/entity.h b/src/core/serverMasterController/data/entity.h new file mode 100644 index 000000000..5b674f24f --- /dev/null +++ b/src/core/serverMasterController/data/entity.h @@ -0,0 +1,47 @@ +#ifndef ENTITY_H +#define ENTITY_H + +#include + +#include +#include + +#include +#include +#include + +namespace cm { +namespace data { + +class CMLIBSHARED_EXPORT Entity : public QObject +{ + Q_OBJECT + +public: + Entity(QObject* parent = nullptr, const QString& key = "SomeEntityKey"); + Entity(QObject* parent, const QString& key, const QJsonObject& jsonObject); + virtual ~Entity(); + +public: + const QString& key() const; + void update(const QJsonObject& jsonObject); + QJsonObject toJson() const; + +signals: + void childCollectionsChanged(const QString& collectionKey); + void childEntitiesChanged(); + void dataDecoratorsChanged(); + +protected: + Entity* addChild(Entity* entity, const QString& key); + EntityCollectionBase* addChildCollection(EntityCollectionBase* entityCollection); + DataDecorator* addDataItem(DataDecorator* dataDecorator); + +protected: + class Implementation; + QScopedPointer implementation; +}; + +}} + +#endif diff --git a/src/core/serverMasterController/data/enumerator-decorator.cpp b/src/core/serverMasterController/data/enumerator-decorator.cpp new file mode 100644 index 000000000..8f9c4c099 --- /dev/null +++ b/src/core/serverMasterController/data/enumerator-decorator.cpp @@ -0,0 +1,73 @@ +#include "enumerator-decorator.h" + +#include + +namespace cm { +namespace data { + +class EnumeratorDecorator::Implementation +{ +public: + Implementation(EnumeratorDecorator* enumeratorDecorator, int value, const std::map& descriptionMapper) + : enumeratorDecorator(enumeratorDecorator) + , value(value) + , descriptionMapper(descriptionMapper) + { + } + + EnumeratorDecorator* enumeratorDecorator{nullptr}; + int value; + std::map descriptionMapper; +}; + +EnumeratorDecorator::EnumeratorDecorator(Entity* parentEntity, const QString& key, const QString& label, int value, const std::map& descriptionMapper) + : DataDecorator(parentEntity, key, label) +{ + implementation.reset(new Implementation(this, value, descriptionMapper)); +} + +EnumeratorDecorator::~EnumeratorDecorator() +{ +} + +int EnumeratorDecorator::value() const +{ + return implementation->value; +} + +QString EnumeratorDecorator::valueDescription() const +{ + if (implementation->descriptionMapper.find(implementation->value) != implementation->descriptionMapper.end()) { + return implementation->descriptionMapper.at(implementation->value); + } else { + return {}; + } +} + +EnumeratorDecorator& EnumeratorDecorator::setValue(int value) +{ + if (value != implementation->value) { + // ...Validation here if required... + implementation->value = value; + emit valueChanged(); + } + + return *this; +} + +QJsonValue EnumeratorDecorator::jsonValue() const +{ + return QJsonValue::fromVariant(QVariant(implementation->value)); +} + +void EnumeratorDecorator::update(const QJsonObject& jsonObject) +{ + if (jsonObject.contains(key())) { + auto valueFromJson = jsonObject.value(key()).toInt(); + setValue(valueFromJson); + } else { + setValue(0); + } +} + +}} diff --git a/src/core/serverMasterController/data/enumerator-decorator.h b/src/core/serverMasterController/data/enumerator-decorator.h new file mode 100644 index 000000000..a31c7bdf1 --- /dev/null +++ b/src/core/serverMasterController/data/enumerator-decorator.h @@ -0,0 +1,44 @@ +#ifndef ENUMERATORDECORATOR_H +#define ENUMERATORDECORATOR_H + +#include + +#include +#include +#include +#include + +#include +#include + +namespace cm { +namespace data { + +class CMLIBSHARED_EXPORT EnumeratorDecorator : public DataDecorator +{ + Q_OBJECT + Q_PROPERTY( int ui_value READ value WRITE setValue NOTIFY valueChanged ) + Q_PROPERTY( QString ui_valueDescription READ valueDescription NOTIFY valueChanged ) + +public: + EnumeratorDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", int value = 0, const std::map& descriptionMapper = std::map()); + ~EnumeratorDecorator(); + + EnumeratorDecorator& setValue(int value); + int value() const; + QString valueDescription() const; + + QJsonValue jsonValue() const override; + void update(const QJsonObject& jsonObject) override; + +signals: + void valueChanged(); + +private: + class Implementation; + QScopedPointer implementation; +}; + +}} + +#endif diff --git a/src/core/serverMasterController/data/int-decorator.cpp b/src/core/serverMasterController/data/int-decorator.cpp new file mode 100644 index 000000000..c010b8220 --- /dev/null +++ b/src/core/serverMasterController/data/int-decorator.cpp @@ -0,0 +1,62 @@ +#include "int-decorator.h" + +#include + +namespace cm { +namespace data { + +class IntDecorator::Implementation +{ +public: + Implementation(IntDecorator* intDecorator, int value) + : intDecorator(intDecorator) + , value(value) + { + } + + IntDecorator* intDecorator{nullptr}; + int value; +}; + +IntDecorator::IntDecorator(Entity* parentEntity, const QString& key, const QString& label, int value) + : DataDecorator(parentEntity, key, label) +{ + implementation.reset(new Implementation(this, value)); +} + +IntDecorator::~IntDecorator() +{ +} + +int IntDecorator::value() const +{ + return implementation->value; +} + +IntDecorator& IntDecorator::setValue(int value) +{ + if(value != implementation->value) { + // ...Validation here if required... + implementation->value = value; + emit valueChanged(); + } + + return *this; +} + +QJsonValue IntDecorator::jsonValue() const +{ + return QJsonValue::fromVariant(QVariant(implementation->value)); +} + +void IntDecorator::update(const QJsonObject& jsonObject) +{ + if (jsonObject.contains(key())) { + auto l_value = jsonObject.value(key()).toInt(); + setValue(l_value); + } else { + setValue(0); + } +} + +}} diff --git a/src/core/serverMasterController/data/int-decorator.h b/src/core/serverMasterController/data/int-decorator.h new file mode 100644 index 000000000..b7fa6699c --- /dev/null +++ b/src/core/serverMasterController/data/int-decorator.h @@ -0,0 +1,42 @@ +#ifndef INTDECORATOR_H +#define INTDECORATOR_H + +#include +#include +#include +#include + +#include +#include + +namespace cm { +namespace data { + +class CMLIBSHARED_EXPORT IntDecorator : public DataDecorator +{ + Q_OBJECT + + Q_PROPERTY( int ui_value READ value WRITE setValue NOTIFY valueChanged ) + +public: + IntDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", int value = 0); + ~IntDecorator(); + + IntDecorator& setValue(int value); + int value() const; + +public: + QJsonValue jsonValue() const override; + void update(const QJsonObject& jsonObject) override; + +signals: + void valueChanged(); + +private: + class Implementation; + QScopedPointer implementation; +}; + +}} + +#endif diff --git a/src/core/serverMasterController/data/string-decorator.cpp b/src/core/serverMasterController/data/string-decorator.cpp new file mode 100644 index 000000000..d32f01062 --- /dev/null +++ b/src/core/serverMasterController/data/string-decorator.cpp @@ -0,0 +1,60 @@ +#include "string-decorator.h" + +#include + +namespace cm { +namespace data { + +class StringDecorator::Implementation +{ +public: + Implementation(StringDecorator* _stringDecorator, const QString& _value) + : stringDecorator(_stringDecorator) + , value(_value) + { + } + + StringDecorator* stringDecorator{nullptr}; + QString value; +}; + +StringDecorator::StringDecorator(Entity* parentEntity, const QString& key, const QString& label, const QString& value) + : DataDecorator(parentEntity, key, label) +{ + implementation.reset(new Implementation(this, value)); +} + +StringDecorator::~StringDecorator() +{ +} + +const QString& StringDecorator::value() const +{ + return implementation->value; +} + +StringDecorator& StringDecorator::setValue(const QString& value) +{ + if(value != implementation->value) { + // ...Validation here if required... + implementation->value = value; + emit valueChanged(); + } + return *this; +} + +QJsonValue StringDecorator::jsonValue() const +{ + return QJsonValue::fromVariant(QVariant(implementation->value)); +} + +void StringDecorator::update(const QJsonObject& _jsonObject) +{ + if (_jsonObject.contains(key())) { + setValue(_jsonObject.value(key()).toString()); + } else { + setValue(""); + } +} + +}} diff --git a/src/core/serverMasterController/data/string-decorator.h b/src/core/serverMasterController/data/string-decorator.h new file mode 100644 index 000000000..0d79e9a93 --- /dev/null +++ b/src/core/serverMasterController/data/string-decorator.h @@ -0,0 +1,41 @@ +#ifndef STRINGDECORATOR_H +#define STRINGDECORATOR_H + +#include +#include +#include +#include +#include + +#include +#include + +namespace cm { +namespace data { + +class CMLIBSHARED_EXPORT StringDecorator : public DataDecorator +{ + Q_OBJECT + Q_PROPERTY( QString ui_value READ value WRITE setValue NOTIFY valueChanged ) + +public: + StringDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", const QString& value = ""); + ~StringDecorator(); + + StringDecorator& setValue(const QString& value); + const QString& value() const; + + QJsonValue jsonValue() const override; + void update(const QJsonObject& jsonObject) override; + +signals: + void valueChanged(); + +private: + class Implementation; + QScopedPointer implementation; +}; + +}} + +#endif