Clarified concepts for Storage and Engine types

Added FilterMover and CardMover to deal with polymorphic ModelCard and Sendfilter types
Implemented more of SenderModelCard (more needed)
This commit is contained in:
Ralph Wessel
2024-09-14 02:06:02 +01:00
parent 90211900e1
commit e75ef3133d
9 changed files with 258 additions and 43 deletions
@@ -25,6 +25,8 @@
210CC8832C80E6A300610F58 /* TriggerEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 210CC8812C80E6A300610F58 /* TriggerEvent.cpp */; };
213CC39C2B1101F500088049 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2151077C2AEDB9070022CD24 /* Cocoa.framework */; };
214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69FBD2C7630B3008B6A06 /* UpdateConfig.cpp */; };
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08262C947F4400CD343B /* CardMover.cpp */; };
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F082C2C94C5C000CD343B /* FilterMover.cpp */; };
219F30422C769283009834E9 /* ConfigTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219F30402C769282009834E9 /* ConfigTests.cpp */; };
21B67CA32C769CB400FD64FC /* libActiveLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69EF52C64FE91008B6A06 /* libActiveLib.a */; };
21B67CA42C769CB400FD64FC /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69ECD2C64C035008B6A06 /* libArchicad27.a */; };
@@ -282,6 +284,10 @@
210CC8822C80E6A300610F58 /* TriggerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TriggerEvent.h; sourceTree = "<group>"; };
213CC3A52B1101F500088049 /* Speckle Connector.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Speckle Connector.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
2151077C2AEDB9070022CD24 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
215F08262C947F4400CD343B /* CardMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CardMover.cpp; sourceTree = "<group>"; };
215F08292C947F4400CD343B /* CardMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardMover.h; sourceTree = "<group>"; };
215F082C2C94C5C000CD343B /* FilterMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilterMover.cpp; sourceTree = "<group>"; };
215F082D2C94C5C000CD343B /* FilterMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterMover.h; sourceTree = "<group>"; };
2161FD902BF2600C006D9527 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
219388682C4E5DE2002A0180 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1020,6 +1026,8 @@
21D0BDD92C9387F70077E104 /* Model */ = {
isa = PBXGroup;
children = (
215F08262C947F4400CD343B /* CardMover.cpp */,
215F08292C947F4400CD343B /* CardMover.h */,
21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */,
21D0BDA92C8F363E0077E104 /* CardSetting.h */,
21D0BDDF2C9393980077E104 /* Filter */,
@@ -1036,6 +1044,8 @@
children = (
21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */,
21D0BDE22C943C630077E104 /* DirectSelectionSendFilter.h */,
215F082C2C94C5C000CD343B /* FilterMover.cpp */,
215F082D2C94C5C000CD343B /* FilterMover.h */,
21D0BDDD2C9393980077E104 /* SendFilter.cpp */,
21D0BDDE2C9393980077E104 /* SendFilter.h */,
);
@@ -1384,8 +1394,10 @@
21B67CAD2C77329800FD64FC /* GetSourceApplicationName.cpp in Sources */,
21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */,
21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */,
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */,
21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */,
21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */,
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */,
21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */,
21F69F8D2C70D7EE008B6A06 /* GetAccounts.cpp in Sources */,
21B67CCC2C77670400FD64FC /* ModelCardDatabase.cpp in Sources */,
@@ -2,6 +2,7 @@
#include "Active/Database/Storage/Storage.h"
#include "Active/Serialise/JSON/JSONTransport.h"
#include "Connector/Record/Model/CardMover.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h"
@@ -20,8 +21,8 @@ using namespace speckle::utility;
namespace connector::database {
///ModelCard database engine declaration
class ModelCardDatabase::Engine : public DocumentStoreEngine<ModelCard, ModelCard, JSONTransport, RecordID> {
using base = DocumentStoreEngine<ModelCard, ModelCard, JSONTransport, RecordID>;
class ModelCardDatabase::Engine : public DocumentStoreEngine<ModelCard, CardMover, JSONTransport, RecordID> {
using base = DocumentStoreEngine<ModelCard, CardMover, JSONTransport, RecordID>;
using base::base;
};
@@ -0,0 +1,56 @@
/*!
Copyright 2024 Ralph Wessel and Hugh Wessel
Distributed under the MIT License (See accompanying file LICENSE.txt or copy at https://opensource.org/license/mit/)
*/
#include "Connector/Record/Model/CardMover.h"
#include "Connector/Record/Model/SenderModelCard.h"
using namespace active::serialise;
using namespace active::utility;
using namespace connector::record;
namespace {
///The tag used to identify a Speckle type name value
const char* attributeTag = "typeDiscriminator";
///Identity for a SenderModelCard
const char* senderCardTypeName = "SenderModelCard";
///Identity for a ReceiverModelCard
const char* receiverCardTypeName = "ReceiverModelCard";
}
///The handler for model card packages
std::shared_ptr<active::serialise::Handler> CardMover::m_handler = std::make_shared<active::serialise::Handler>(attributeTag);
/*--------------------------------------------------------------------
Constructor (for deserialisation)
handler: A package handler to reconstruct incoming packages
--------------------------------------------------------------------*/
CardMover::CardMover() : Mover{m_handler} {
validateHandler();
} //CardMover::CardMover
/*--------------------------------------------------------------------
Constructor (for serialisation)
outgoing: An outgoing package
--------------------------------------------------------------------*/
CardMover::CardMover(const active::serialise::Package& outgoing) : Mover{outgoing, m_handler} {
validateHandler();
} //CardMover::CardMover
/*--------------------------------------------------------------------
Ensure the handler is populated
--------------------------------------------------------------------*/
void CardMover::validateHandler() {
if (!m_handler->empty())
return;
m_handler->add<SenderModelCard>(senderCardTypeName);
} //CardMover::validateHandler
@@ -0,0 +1,41 @@
#ifndef CONNECTOR_MODEL_CARD_MOVER
#define CONNECTOR_MODEL_CARD_MOVER
#include "Active/Serialise/Package/Wrapper/Mover.h"
namespace connector::record {
/*!
Wrapper to box/unbox objects during (de)serialisation, reading/writing a specified attribute to determine object type
Note that a derived class could also define the package handler, allowing the wrapper to be created via a default constructor that is
automatically bound to a set of internally defined object types
*/
class CardMover : public active::serialise::Mover {
public:
// MARK: - Constructors
/*!
Default constructor
*/
CardMover();
/*!
Constructor (for serialisation)
@param outgoing An outgoing package
*/
CardMover(const active::serialise::Package& outgoing);
private:
/*!
Ensure the handler is populated
*/
static void validateHandler();
///The handler for model card packages
static std::shared_ptr<active::serialise::Handler> m_handler;
};
}
#endif //CONNECTOR_MODEL_CARD_MOVER
@@ -0,0 +1,64 @@
/*!
Copyright 2024 Ralph Wessel and Hugh Wessel
Distributed under the MIT License (See accompanying file LICENSE.txt or copy at https://opensource.org/license/mit/)
*/
#include "Connector/Record/Model/Filter/FilterMover.h"
#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h"
using namespace active::serialise;
using namespace active::utility;
using namespace connector::record;
namespace {
///The tag used to identify a Speckle type name value
const char* attributeTag = "typeDiscriminator";
///Identity for a SenderModelCard
const char* DirectSelectionTypeName = "DirectSelectionSendFilter";
}
///The handler for model card packages
std::shared_ptr<active::serialise::Handler> FilterMover::m_handler = std::make_shared<active::serialise::Handler>(attributeTag);
/*--------------------------------------------------------------------
Constructor (for deserialisation)
handler: A package handler to reconstruct incoming packages
--------------------------------------------------------------------*/
FilterMover::FilterMover() : Mover{m_handler} {
validateHandler();
} //FilterMover::FilterMover
/*--------------------------------------------------------------------
Constructor (for serialisation)
outgoing: An outgoing package
--------------------------------------------------------------------*/
FilterMover::FilterMover(const active::serialise::Package& outgoing) : Mover{outgoing, m_handler} {
validateHandler();
} //FilterMover::FilterMover
/*--------------------------------------------------------------------
Constructor (when it will be used for serialisation only on an existing object)
package: A reference to the member variable
--------------------------------------------------------------------*/
FilterMover::FilterMover(active::serialise::PackageUniqueWrap&& package) : Mover{std::move(package), m_handler} {
} //FilterMover::FilterMover
/*--------------------------------------------------------------------
Ensure the handler is populated
--------------------------------------------------------------------*/
void FilterMover::validateHandler() {
if (!m_handler->empty())
return;
m_handler->add<DirectSelectionSendFilter>(DirectSelectionTypeName);
} //FilterMover::validateHandler
@@ -0,0 +1,51 @@
#ifndef CONNECTOR_MODEL_SEND_FILTER_MOVER
#define CONNECTOR_MODEL_SEND_FILTER_MOVER
#include "Active/Serialise/Package/Wrapper/Mover.h"
namespace connector::record {
/*!
Wrapper to box/unbox objects during (de)serialisation, reading/writing a specified attribute to determine object type
Note that a derived class could also define the package handler, allowing the wrapper to be created via a default constructor that is
automatically bound to a set of internally defined object types
*/
class FilterMover : public active::serialise::Mover {
public:
// MARK: - Constructors
/*!
Default constructor (primarily for a list of polymorphic objects)
*/
FilterMover();
/*!
Constructor (when it will be used for serialisation only on an existing object)
@param package A reference to the member variable
*/
FilterMover(const Package& package);
/*!
Constructor (for serialisation or deserialisation of a polymorphic member variable held in a unique pointer)
@param package A reference to the member variable
*/
FilterMover(const Package::Unique& package);
/*!
Constructor (when it will be used for serialisation only on an existing object)
@param package A reference to the member variable
*/
FilterMover(active::serialise::PackageUniqueWrap&& package);
private:
/*!
Ensure the handler is populated
*/
static void validateHandler();
///The handler for model card packages
static std::shared_ptr<active::serialise::Handler> m_handler;
};
}
#endif //CONNECTOR_MODEL_SEND_FILTER_MOVER
@@ -1,5 +1,8 @@
#include "Connector/Record/Model/SenderModelCard.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageUniqueWrap.h"
#include "Connector/Record/Model/Filter/FilterMover.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
#include <array>
@@ -67,16 +70,12 @@ SenderModelCard::~SenderModelCard() {
--------------------------------------------------------------------*/
bool SenderModelCard::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
/* inventory.merge(Inventory{
inventory.merge(Inventory{
{
{ fieldID[modelID], modelID, element },
{ fieldID[projectID], projectID, element },
{ fieldID[accountID], accountID, element },
{ fieldID[serverURLID], serverURLID, element },
{ fieldID[settingsID], settingsID, element },
{ fieldID[sendFilterID], sendFilterID, element },
},
}.withType(&typeid(SenderModelCard)));
return base::fillInventory(inventory);*/
return base::fillInventory(inventory);
} //SenderModelCard::fillInventory
@@ -88,23 +87,15 @@ bool SenderModelCard::fillInventory(Inventory& inventory) const {
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SenderModelCard::getCargo(const Inventory::Item& item) const {
/* if (item.ownerType != &typeid(SenderModelCard))
if (item.ownerType != &typeid(SenderModelCard))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case modelID:
return std::make_unique<ValueWrap<String>>(m_modelID);
case projectID:
return std::make_unique<ValueWrap<String>>(m_projectID);
case accountID:
return std::make_unique<ValueWrap<String>>(m_accountID);
case serverURLID:
return std::make_unique<ValueWrap<String>>(m_serverURL);
case settingsID:
return std::make_unique<ContainerWrap<Vector, CardSetting>>(m_settings);
case sendFilterID:
return std::make_unique<FilterMover>(PackageUniqueWrap{m_filter});
default:
return nullptr; //Requested an unknown index
}*/
}
} //SenderModelCard::getCargo
@@ -112,10 +103,6 @@ Cargo::Unique SenderModelCard::getCargo(const Inventory::Item& item) const {
Set to the default package content
--------------------------------------------------------------------*/
void SenderModelCard::setDefault() {
/* base::setDefault();
m_modelID.clear();
m_projectID.clear();
m_accountID.clear();
m_serverURL.clear();
m_settings.clear();*/
base::setDefault();
m_filter->setDefault();
} //SenderModelCard::setDefault
@@ -1,6 +1,7 @@
#ifndef SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
#define SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
#include "Active/Database/Concepts.h"
#include "Active/Database/Storage/DBaseEngine.h"
#include "Active/Database/Storage/RecordCache.h"
#include "Active/File/Path.h"
@@ -21,8 +22,9 @@
namespace speckle::database {
///Concept for the ability to store objects in a document
template<typename Obj, typename Transport>
concept DocumentStorable = std::is_base_of_v<active::serialise::Cargo, Obj> &&
template<typename Obj, typename ObjWrapper, typename Transport>
concept DocumentStorable = (active::database::CanWrap<Obj, ObjWrapper> || active::database::FlatType<Obj, ObjWrapper>) &&
std::is_base_of_v<active::serialise::Cargo, Obj> &&
std::is_base_of_v<active::serialise::Transport, Transport>;
/*!
@@ -36,7 +38,7 @@ namespace speckle::database {
@tparam ObjID The object identifier type, e.g. Guid
*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID = RecordID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine<Obj, ObjID, RecordID, RecordID> {
public:
@@ -45,7 +47,7 @@ namespace speckle::database {
using base = active::database::DBaseEngine<Obj, ObjID, RecordID, RecordID>;
using Filter = base::Filter;
using Outline = base::Outline;
using Cache = active::database::RecordCache<Obj, ObjID, RecordID, RecordID>;
using Cache = active::database::RecordCache<Obj, ObjWrapper, ObjID, RecordID, RecordID>;
// MARK: - Constructors
@@ -147,7 +149,7 @@ namespace speckle::database {
return: The cached records (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
typename DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::Cache* DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getCache() const {
if (m_cache)
return m_cache.get();
@@ -175,7 +177,7 @@ namespace speckle::database {
return: The requested object (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
std::unique_ptr<Obj> DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObject(const ObjID& ID, std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
return getCache()->read(ID);
@@ -191,7 +193,7 @@ namespace speckle::database {
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
active::container::Vector<Obj> DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObjects(std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
return getCache()->read();
@@ -208,7 +210,7 @@ namespace speckle::database {
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
active::container::Vector<Obj> DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObjects(const Filter& filter, std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
return getCache()->read(filter);
@@ -225,7 +227,7 @@ namespace speckle::database {
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::write(const Obj& object, const ObjID& objID, std::optional<ObjID> objDocID,
std::optional<RecordID> tableID, std::optional<RecordID> documentID) const {
getCache()->write(object); //NB: In future we might support duplicating records if objID != obj.id
@@ -242,7 +244,7 @@ namespace speckle::database {
return: True if the object was successfully erased
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase(const ObjID& ID, std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
getCache()->erase(ID);
@@ -256,7 +258,7 @@ namespace speckle::database {
documentID: Optional document ID (filter for this document only - nullopt = all objects)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase(std::optional<RecordID> tableID, std::optional<RecordID> documentID) const {
getCache()->erase();
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase
@@ -268,7 +270,7 @@ namespace speckle::database {
return: The database outline
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::Outline DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getOutline() const {
Outline result;
if (getSchema().empty())
@@ -285,7 +287,7 @@ namespace speckle::database {
return: Data to store from the latest records
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
active::utility::Memory DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::buildStore() {
active::utility::Memory result;
Transport().send(std::forward<active::serialise::Cargo&&>(*getCache()), active::serialise::Identity{}, result);
@@ -301,7 +303,7 @@ namespace speckle::database {
return: The merged data to be stored
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::mergeStore(const active::utility::Memory& toMerge) {
//Import the incoming records from the data to merge
Cache incoming;
@@ -1,7 +1,8 @@
#include "Speckle/Record/Credentials/ServerInfo.h"
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageUnoWrap.h"
#include "Active/Serialise/Package/Wrapper/Mover.h"
#include "Active/Serialise/Package/Wrapper/PackageUniqueWrap.h"
#include "Speckle/Utility/Guid.h"
#include <array>
@@ -90,7 +91,7 @@ Cargo::Unique ServerInfo::getCargo(const Inventory::Item& item) const {
case urlID:
return std::make_unique<StringOptWrap>(m_url);
case migrationID:
return std::make_unique<PackageUnoWrap<ServerMigration>>(m_migration);
return std::make_unique<Mover>(PackageUniqueWrap{m_migration});
default:
return nullptr; //Requested an unknown index
}