From 7fe5ba6e9dc12220b23cb9b11d211ef23d4ab430 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Mon, 9 Sep 2024 16:45:41 +0100 Subject: [PATCH 01/16] Defined CardSetting and ModelCard classes --- .../Connector.xcodeproj/project.pbxproj | 12 ++ .../Database/Model/Card/CardSetting.cpp | 93 +++++++++++++++ .../Database/Model/Card/CardSetting.h | 107 ++++++++++++++++++ .../Database/Model/Card/ModelCard.cpp | 100 ++++++++++++++++ .../Connector/Database/Model/Card/ModelCard.h | 105 +++++++++++++++++ 5 files changed, 417 insertions(+) create mode 100644 SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp create mode 100644 SpeckleConnector/Connector/Database/Model/Card/CardSetting.h create mode 100644 SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp create mode 100644 SpeckleConnector/Connector/Database/Model/Card/ModelCard.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index 028a510..66e1975 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ 21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD8D2C8EE4490077E104 /* Send.cpp */; }; 21D0BD972C8F13F30077E104 /* GetSendFilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */; }; 21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD982C8F154B0077E104 /* SendFilter.cpp */; }; + 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */; }; + 21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */; }; 21D1E9AD2BF14AF200957EAA /* BIMData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9152BF14AEC00957EAA /* BIMData.framework */; }; 21D1E9AE2BF14AF200957EAA /* TeamworkPortalServerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */; }; 21D1E9AF2BF14AF200957EAA /* GDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9172BF14AEC00957EAA /* GDL.framework */; }; @@ -321,6 +323,10 @@ 21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSendFilters.cpp; sourceTree = ""; }; 21D0BD982C8F154B0077E104 /* SendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendFilter.cpp; sourceTree = ""; }; 21D0BD992C8F154B0077E104 /* SendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendFilter.h; sourceTree = ""; }; + 21D0BDA42C8F33AC0077E104 /* ModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelCard.h; sourceTree = ""; }; + 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModelCard.cpp; sourceTree = ""; }; + 21D0BDA92C8F363E0077E104 /* CardSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardSetting.h; sourceTree = ""; }; + 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CardSetting.cpp; sourceTree = ""; }; 21D1E9152BF14AEC00957EAA /* BIMData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BIMData.framework; path = "../Archicad 27/Support/Frameworks/BIMData.framework"; sourceTree = ""; }; 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TeamworkPortalServerClient.framework; path = "../Archicad 27/Support/Frameworks/TeamworkPortalServerClient.framework"; sourceTree = ""; }; 21D1E9172BF14AEC00957EAA /* GDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GDL.framework; path = "../Archicad 27/Support/Frameworks/GDL.framework"; sourceTree = ""; }; @@ -918,6 +924,10 @@ 21B67CC92C77670400FD64FC /* Card */ = { isa = PBXGroup; children = ( + 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */, + 21D0BDA92C8F363E0077E104 /* CardSetting.h */, + 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */, + 21D0BDA42C8F33AC0077E104 /* ModelCard.h */, 21B67CC72C77670400FD64FC /* ModelCardDatabase.cpp */, 21B67CC82C77670400FD64FC /* ModelCardDatabase.h */, ); @@ -1324,6 +1334,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */, 21B67CE32C78D1FB00FD64FC /* SayHiArg.cpp in Sources */, 21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */, 21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */, @@ -1344,6 +1355,7 @@ 21B67CC02C775A0D00FD64FC /* GetDocumentInfo.cpp in Sources */, 21B67CE72C78D23B00FD64FC /* ConnectorConfig.cpp in Sources */, 21B67CAD2C77329800FD64FC /* GetSourceApplicationName.cpp in Sources */, + 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */, 21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */, 21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */, 21F69F8D2C70D7EE008B6A06 /* GetAccounts.cpp in Sources */, diff --git a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp b/SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp new file mode 100644 index 0000000..e38db56 --- /dev/null +++ b/SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp @@ -0,0 +1,93 @@ +#include "Connector/Database/Model/Card/CardSetting.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Item/Wrapper/AnyValueWrap.h" + +#include + +using namespace active::serialise; +using namespace connector::database; +using namespace speckle::utility; + +namespace { + + ///Serialisation fields + enum FieldIndex { + idID, + titleID, + typeID, + valueID, + enumID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"id"}, + Identity{"title"}, + Identity{"type"}, + Identity{"value"}, + Identity{"enum"}, + }; + +} + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool CardSetting::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[idID], idID, element }, + { fieldID[titleID], titleID, element }, + { fieldID[typeID], typeID, element }, + { fieldID[valueID], valueID, element }, + { fieldID[enumID], enumID, element }, + }, + }.withType(&typeid(CardSetting))); + return true; +} //CardSetting::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique CardSetting::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(CardSetting)) + return nullptr; + using namespace active::serialise; + switch (item.index) { + case idID: + return std::make_unique>(m_ID); + case titleID: + return std::make_unique>(m_title); + case typeID: + return std::make_unique>(m_type); + case valueID: + return std::make_unique(*m_value); + case enumID: + return std::make_unique>(m_type); + default: + return nullptr; //Requested an unknown index + } +} //CardSetting::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void CardSetting::setDefault() { + m_ID.clear(); + m_title.clear(); + m_type.clear(); + m_value->setDefault(); + m_enum.clear(); +} //CardSetting::setDefault diff --git a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h b/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h new file mode 100644 index 0000000..752dc51 --- /dev/null +++ b/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h @@ -0,0 +1,107 @@ +#ifndef CONNECTOR_DATABASE_MODEL_CARD_SETTING +#define CONNECTOR_DATABASE_MODEL_CARD_SETTING + +#include "Active/Serialise/Package/Package.h" +#include "Active/Setting/ValueSetting.h" +#include "Active/Setting/Values/StringValue.h" +#include "Active/Utility/Cloner.h" +#include "Speckle/Utility/Guid.h" +#include "Speckle/Utility/String.h" + +namespace connector::database { + + /*! + A setting attached to a model card, capturing rendering/view states of the model at the time of sending, e.g. level of detail (LoD) + */ + class CardSetting : public active::serialise::Package, public active::utility::Cloner { + public: + + // MARK: - Types + + using base = active::serialise::Package; + + // MARK: - Constructors + + /*! + Default constructor + */ + CardSetting() {} + /*! + Copy constructor + @param source The object to copy + */ + CardSetting(const CardSetting& source) : + m_title{source.m_title}, m_type{source.m_type}, m_value{clone(*source.m_value)}, m_enum{source.m_enum} {} + /*! + Destructor + */ + ~CardSetting() {} + /*! + Record cloning + @return A clone of this record + */ + virtual CardSetting* clonePtr() const override { return new CardSetting(*this); }; + + // MARK: - Functions (const) + + /*! + Get the setting ID + @return The setting ID + */ + const speckle::utility::String& getID() const { return m_ID; } + /*! + Get the setting title + @return The setting title + */ + const speckle::utility::String& getTitle() const { return m_title; } + /*! + Get the setting type + @return The setting type + */ + const speckle::utility::String& getType() const { return m_type; } + /*! + Get the setting value + @return The setting value + */ + const active::setting::Value& getValue() const { return *m_value; } + /*! + Get the options for the value, i.e. possible values it can hold + @return Possible setting values + */ + std::vector getEnum() const { return m_enum; } + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + ///A unique ID for the setting + speckle::utility::String m_ID = {speckle::utility::Guid{true}}; + ///The model ID + speckle::utility::String m_title; + ///The project ID + speckle::utility::String m_type; + ///The setting value + active::setting::Value::Unique m_value = std::make_unique(); + ///Possible values for the setting (as strings) + std::vector m_enum; + }; + +} + +#endif //CONNECTOR_DATABASE_MODEL_CARD_SETTING diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp new file mode 100644 index 0000000..d6030d0 --- /dev/null +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp @@ -0,0 +1,100 @@ +#include "Connector/Database/Model/Card/ModelCard.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" + +#include + +using namespace active::container; +using namespace active::serialise; +using namespace connector::database; +using namespace speckle::utility; + +namespace { + + ///Serialisation fields + enum FieldIndex { + idID, + modelID, + projectID, + accountID, + serverURLID, + settingsID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"id"}, + Identity{"modelId"}, + Identity{"projectId"}, + Identity{"accountId"}, + Identity{"serverURL"}, + Identity{"settings"}, + }; + +} + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool ModelCard::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[idID], idID, element }, + { fieldID[modelID], modelID, element }, + { fieldID[projectID], projectID, element }, + { fieldID[accountID], accountID, element }, + { fieldID[serverURLID], serverURLID, element }, + { fieldID[settingsID], settingsID, element }, + }, + }.withType(&typeid(ModelCard))); + return true; +} //ModelCard::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique ModelCard::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(ModelCard)) + return nullptr; + using namespace active::serialise; + switch (item.index) { + case idID: + return std::make_unique>(m_ID); + case modelID: + return std::make_unique>(m_modelID); + case projectID: + return std::make_unique>(m_projectID); + case accountID: + return std::make_unique>(m_accountID); + case serverURLID: + return std::make_unique>(m_serverURL); + case settingsID: + return std::make_unique>(m_settings); + default: + return nullptr; //Requested an unknown index + } +} //ModelCard::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void ModelCard::setDefault() { + m_ID.clear(); + m_modelID.clear(); + m_projectID.clear(); + m_accountID.clear(); + m_serverURL.clear(); + m_settings.clear(); +} //ModelCard::setDefault diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h new file mode 100644 index 0000000..23339f8 --- /dev/null +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h @@ -0,0 +1,105 @@ +#ifndef CONNECTOR_DATABASE_MODEL_CARD +#define CONNECTOR_DATABASE_MODEL_CARD + +#include "Active/Container/Vector.h" +#include "Active/Serialise/Package/Package.h" +#include "Active/Utility/Cloner.h" +#include "Connector/Database/Model/Card/CardSetting.h" +#include "Speckle/Utility/String.h" + +namespace connector::database { + + /*! + A connector send filter + */ + class ModelCard : public active::serialise::Package, public active::utility::Cloner { + public: + + // MARK: - Types + + using base = active::serialise::Package; + //List of card settings + using SettingList = active::container::Vector; + + // MARK: - Constructors + + /*! + Default constructor + */ + ModelCard() {} + /*! + Record cloning + @return A clone of this record + */ + virtual ModelCard* clonePtr() const override { return new ModelCard(*this); }; + + // MARK: - Functions (const) + + /*! + Get the card ID + @return The card ID + */ + const speckle::utility::String& getID() const { return m_ID; } + /*! + Get the model ID + @return The model ID + */ + const speckle::utility::String& getModelID() const { return m_modelID; } + /*! + Get the setting type + @return The setting type + */ + const speckle::utility::String& getProjectID() const { return m_projectID; } + /*! + Get the setting type + @return The setting type + */ + const speckle::utility::String& getAccountID() const { return m_accountID; } + /*! + Get the setting type + @return The setting type + */ + const speckle::utility::String& getServerURL() const { return m_serverURL; } + /*! + Get the card settings + @return The card settings + */ + const SettingList& getSettings() const { return m_settings; } + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + ///A unique ID for the card (not the ID of the linked model) + speckle::utility::String m_ID; + ///The model ID + speckle::utility::String m_modelID; + ///The project ID + speckle::utility::String m_projectID; + ///The user account ID + speckle::utility::String m_accountID; + ///The server URL + speckle::utility::String m_serverURL; + ///Settings for the model rendering, e.g. level of detail (LoD) + SettingList m_settings; + }; + +} + +#endif //CONNECTOR_DATABASE_MODEL_CARD From 7d9f939b8bd6a0b4380f5fecadc0b8af618ee290 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Tue, 10 Sep 2024 22:28:29 +0100 Subject: [PATCH 02/16] Added DocumentStoreCore Added DocumentStoreEngine Added Addon::isSharedDocument --- .../Database/Model/Card/ModelCardDatabase.h | 1 + .../DocumentStore/DocumentStoreCore.cpp | 175 +++++++++++ .../Storage/DocumentStore/DocumentStoreCore.h | 91 ++++++ .../DocumentStore/DocumentStoreEngine.h | 283 ++++++++++++++++++ SpeckleLib/Speckle/Environment/Addon.cpp | 18 +- SpeckleLib/Speckle/Environment/Addon.h | 5 + .../Speckle/Interface/Browser/JSPortal.h | 4 +- SpeckleLib/Speckle/Utility/Guid.h | 6 + .../SpeckleLib.xcodeproj/project.pbxproj | 30 +- 9 files changed, 609 insertions(+), 4 deletions(-) create mode 100644 SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp create mode 100644 SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h create mode 100644 SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h index 8ff7d31..39a61f3 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h @@ -2,6 +2,7 @@ #define CONNECTOR_DATABASE_MODEL_CARD_DATABASE #include "Active/Serialise/Package/Package.h" +#include "Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h" #include "Speckle/Utility/String.h" namespace connector::database { diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp new file mode 100644 index 0000000..36cbee2 --- /dev/null +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -0,0 +1,175 @@ +#include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h" + +#include "Active/Utility/Memory.h" +#include "Active/Utility/String.h" +#include "Speckle/Environment/Addon.h" +#include "Speckle/Utility/Guid.h" +#include "Speckle/Utility/String.h" + +#ifdef ARCHICAD +#include +#include +#endif + +using namespace active::setting; +using namespace speckle::database; +using namespace speckle::environment; +using namespace speckle::utility; + +using enum DocumentStoreCore::Status; + +namespace { + +#ifdef ARCHICAD + /*-------------------------------------------------------------------- + Convert an Archicad API error code to a DocumentStoreCore status + + acErrorCode: The API error code + + return: An equivalent status code + --------------------------------------------------------------------*/ + DocumentStoreCore::Status convertArchicadError(long acErrorCode) { + using enum DocumentStoreCore::Status; + switch (acErrorCode) { + case NoError: + return nominal; + case APIERR_BADPARS: + return badParameter; + case APIERR_BADID: + return badID; + default: + break; + } + return error; + } //convertArchicadError + + + /*-------------------------------------------------------------------- + Determine if a specified data store exists + + id: The store identity + + return: True if the store exists + --------------------------------------------------------------------*/ + bool isExistingStore(active::utility::NameID& storeID) { + if (storeID.id) + return true; //We must have a store if the ID is populated + bool isStoreFound = false; +#ifdef ARCHICAD + API_Guid acID; + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectGuidFromName(String{storeID.name}, &acID)); statusCode != nominal) + throw std::system_error(DocumentStoreCore::makeError(statusCode)); + storeID.id = Guid{acID}; + isStoreFound = true; +#endif + return isStoreFound; + } //isExistingStore + +#endif + + ///Category for DocumentStore processing errors + class DocumentStoreCategory : public std::error_category { + public: + ///Category name + const char* name() const noexcept override { + return "active::database::sqlite::category"; + } + /*! + Get a message for a specified error code + @param errorCode A DocumentStore processing code + @return The error message for the specified code + */ + std::string message(int errorCode) const override { + //TODO: These error messages are ok for developers - but can we help users more? + switch (static_cast(errorCode)) { + case nominal: + return ""; + case badParameter: + return "An internal function has been incorrectly used"; + case badID: + return "Internal data has been requested using an invalid identity"; + case error: + return "A non-specific error occurred"; + default: + return "An unknown error occurred"; + } + } + }; + + ///DocumentStore processing category error instance + static DocumentStoreCategory instance; + +} + +/*-------------------------------------------------------------------- + Make an error code for DocumentStore processing + + return: An STL error code + --------------------------------------------------------------------*/ +std::error_code DocumentStoreCore::makeError(DocumentStoreCore::Status code) { + return std::error_code(static_cast(code), instance); +} //DocumentStoreCore::makeError + + +/*-------------------------------------------------------------------- + Read the data stored in the document + + return: The stored data (empty if the data doesn't exist) + --------------------------------------------------------------------*/ +active::utility::Memory DocumentStoreCore::readStore() const { + active::utility::Memory result; + //First establish that we actually have stored data to read + if (!isExistingStore(m_id)) + return result; + //Read the stored data +#ifdef ARCHICAD + GS::UniString storeName{String{m_id.name}}; + GSHandle storedData; + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectContent(Guid{m_id.id}, &storeName, &storedData)); statusCode != nominal) + throw std::system_error(makeError(statusCode)); + //Copy the stored data into the result + auto storeSize = BMGetHandleSize(storedData); + result.resize(storeSize); + active::utility::Memory::copy(result.data(), *storedData, storeSize, storeSize); + BMKillHandle(&storedData); +#endif + return result; +} //DocumentStoreCore::readStore + + +/*-------------------------------------------------------------------- + Write the data to document storage + + toWrite: The data to write to storage + --------------------------------------------------------------------*/ +void DocumentStoreCore::writeStore() { +#ifdef ARCHICAD + //Ensure a suitable data store exists + if (!isExistingStore(m_id)) { + //Create when missing + API_Guid acID; + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_CreateUniqueObject(String{m_id.name}, &acID)); statusCode != nominal) + throw std::system_error(makeError(statusCode)); + m_id = Guid{acID}; + } + //Reserve the storage object in TW + if (addon()->isSharedDocument()) { + GS::HashTable conflicts; + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ReserveObjects({Guid{m_id.id}}, &conflicts)); statusCode != nominal) + throw std::system_error(makeError(statusCode)); + //TODO: Implamenent handling for conflicts + } + auto toWrite = buildStore(); + //Write the new data + GSHandle output = BMAllocateHandle(static_cast(toWrite.size()), ALLOCATE_CLEAR, 0); + active::utility::Memory::copy(*output, toWrite.data(), toWrite.size(), toWrite.size()); + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ModifyObject({Guid{m_id.id}}, nullptr, &output)); statusCode != nominal) + throw std::system_error(makeError(statusCode)); + BMKillHandle(&output); + //Release the storage object in TW + if (addon()->isSharedDocument()) { + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ReleaseObjects({Guid{m_id.id}})); statusCode != nominal) + throw std::system_error(makeError(statusCode)); + } +#endif +} //DocumentStoreCore::writeStore diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h new file mode 100644 index 0000000..7a81aa1 --- /dev/null +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h @@ -0,0 +1,91 @@ +#ifndef SPECKLE_DATABASE_DOCUMENT_STORE_CORE +#define SPECKLE_DATABASE_DOCUMENT_STORE_CORE + +#include "Active/File/Path.h" +#include "Active/Setting/SettingList.h" +#include "Active/Database/Storage/DBaseSchema.h" +#include "Active/Utility/NameID.h" + +namespace speckle::database { + + /*! + Core functionality and definitions for a mechanism to store data in a BIM (3rd-party) document/database + + Currently implement for Archicad Add-On Objects + */ + class DocumentStoreCore { + public: + + // MARK: - Types + + ///Status of of the DocumentStore database + enum class Status { + nominal, /// +#include + +namespace speckle::database { + + ///Concept for the ability to store objects in a document + template + concept DocumentStorable = std::is_base_of_v && + std::is_base_of_v; + + /*! + A database engine to store records in a 3rd-party BIM document + + Due to the fact that these records are intended to represent a single table and are stored in a document, the concepts of 'table' and + 'document' aren't currently applicable (this could be extended in future if there is a use-case) + @tparam Obj Interface for the stored object. NB: This can be a base class for an object hierarchy, not necessarily a concrete class + @tparam Transport The serialisation transport mechanism for objects + @tparam ObjID The object identifier type, e.g. Guid + */ + template + requires DocumentStorable + class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { + public: + + // MARK: - Types + + using base = active::database::DBaseEngine; + using Filter = base::Filter; + using Cache = active::database::RecordCache; + + // MARK: - Constructors + + /*! + Constructor + @param id The document storage identifier + */ + DocumentStoreEngine(const active::utility::NameID& id) : DocumentStoreCore{id} {} + /*! + Copy constructor + @param source The object to copy + */ + DocumentStoreEngine(const DocumentStoreEngine& source) : DocumentStoreCore{source}, base{source} { + m_cache = (source.m_cache) ? std::make_unique(*source.m_cache) : nullptr; + } + /*! + Object cloning + @return A clone of this object + */ + DocumentStoreEngine* clonePtr() const override { return new DocumentStoreEngine{*this}; } + + // MARK: - Functions (const) + + /*! + Get an object by index + @param ID The object ID + @param tableID Optional table ID (defaults to the first table) + @param documentID Optional document ID (when the object is bound to a specific document) + @return The requested object (nullptr on failure) + */ + std::unique_ptr getObject(const ObjID& ID, utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + /*! + Get all objects + @param tableID Optional table ID (defaults to the first table) + @param documentID Optional document ID (filter for this document only - nullopt = all objects) + @return The requested objects (nullptr on failure) + */ + active::container::Vector getObjects(utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + /*! + Get a filtered list of objects + @param filter The object filter + @param tableID Optional table ID (defaults to the first table) + @param documentID Optional document ID (filter for this document only - nullopt = all objects) + @return The filtered objects (nullptr on failure) + */ + active::container::Vector getObjects(const Filter& filter, utility::String::Option tableID = std::nullopt, + utility::String::Option documentID = std::nullopt) const override; + /*! + Erase an object by index + @param ID The object ID + @param tableID Optional table ID (defaults to the first table) + @param documentID Optional document ID (when the object is bound to a specific document) + @throw Exception thrown on SQL error + */ + void erase(const ObjID& ID, utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + /*! + Erase all objects + @param tableID Optional table ID (defaults to the first table) + @param documentID Optional document ID (when the object is bound to a specific document) + @throw Exception thrown on SQL error + */ + void erase(utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + protected: + /*! + Get the cache of records built from the data stored in the document + @return The cached records + */ + Cache* getCache() const; + /*! + Build new store data from the latest records + @return Data to store from the latest records + */ + active::utility::Memory buildStore() override; + /*! + Merge existing stored data with incoming stored data (from an external source) + @param toMerge The external stored data to merge + @return The merged data to be stored + */ + active::utility::Memory mergeStore(const active::utility::Memory& toMerge) override; + /*! + Reset the stored data (some external change has invalidated previous data, e.g. the document was closed) + */ + void resetStore() override { m_cache.reset(); } + + private: + //Cached records from the document store + std::unique_ptr m_cache; + }; + + /*-------------------------------------------------------------------- + Get the cache of records built from the data stored in the document + + return: The cached records (nullptr on failure) + --------------------------------------------------------------------*/ + template + requires DocumentStorable + typename DocumentStoreEngine::Cache* DocumentStoreEngine::getCache() const { + if (m_cache) + return m_cache; + //Read the data stored in the document + auto storedData = readStore(); + m_cache = std::make_unique(); + if (!storedData) + return m_cache; //Return an empty container if there's no data + //Import the document data into the record cache + Transport().receive(std::forward(*m_cache), active::serialise::Identity{}, storedData); + return m_cache; + } //DocumentStoreEngine::getCache + + + /*-------------------------------------------------------------------- + Get an object by index + + index: The object index + tableID: Optional table ID (defaults to the first table) + documentID: Optional document ID (when the object is bound to a specific document) + + return: The requested object (nullptr on failure) + --------------------------------------------------------------------*/ + template + requires DocumentStorable + std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, utility::String::Option tableID, + utility::String::Option documentID) const { + auto cache = getCache(); + return cache ? cache->read(ID) : nullptr; + } //DocumentStoreEngine::getObject + + + /*-------------------------------------------------------------------- + Get all objects + + tableID: Optional table ID (defaults to the first table) + documentID: Optional document ID (filter for this document only - nullopt = all objects) + + return: The requested objects (nullptr on failure) + --------------------------------------------------------------------*/ + template + requires DocumentStorable + active::container::Vector DocumentStoreEngine::getObjects(utility::String::Option tableID, + utility::String::Option documentID) const { + auto cache = getCache(); + return cache ? cache->read() : nullptr; + } //DocumentStoreEngine::getObjects + + + /*-------------------------------------------------------------------- + Get all objects + + filter: The object filter + tableID: Optional table ID (defaults to the first table) + documentID: Optional document ID (filter for this document only - nullopt = all objects) + + return: The requested objects (nullptr on failure) + --------------------------------------------------------------------*/ + template + requires DocumentStorable + active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, utility::String::Option tableID, + utility::String::Option documentID) const { + auto cache = getCache(); + return cache ? cache->read(filter) : nullptr; + } //DocumentStoreEngine::getObjects + + + /*-------------------------------------------------------------------- + Erase an object by index + + objID: The object ID + tableID: Optional table ID (defaults to the first table) + documentID: Optional document ID (when the object is bound to a specific document) + + return: True if the object was successfully erased + --------------------------------------------------------------------*/ + template + requires DocumentStorable + void DocumentStoreEngine::erase(const ObjID& ID, utility::String::Option tableID, + utility::String::Option documentID) const { + auto cache = getCache(); + if (cache) + cache->erase(ID); + } //DocumentStoreEngine::erase + + + /*-------------------------------------------------------------------- + Erase all objects + + tableID: Optional table ID (defaults to the first table) + documentID: Optional document ID (filter for this document only - nullopt = all objects) + --------------------------------------------------------------------*/ + template + requires DocumentStorable + void DocumentStoreEngine::erase(utility::String::Option tableID, utility::String::Option documentID) const { + auto cache = getCache(); + if (cache) + cache->erase(); + } //DocumentStoreEngine::erase + + + /*-------------------------------------------------------------------- + Build new store data from the latest records + + return: Data to store from the latest records + --------------------------------------------------------------------*/ + template + requires DocumentStorable + active::utility::Memory DocumentStoreEngine::buildStore() { + active::utility::Memory result; + auto cache = getCache(); + if (!cache) + cache = std::make_unique(); //We still want to export an empty cache object even if it contains no records + //Export the cached records + Transport().send(std::forward(*m_cache), active::serialise::Identity{}, result); + return result; + } //DocumentStoreEngine::buildStore + + + /*-------------------------------------------------------------------- + Merge existing stored data with incoming stored data (from an external source) + + toMerge: The external stored data to merge + + return: The merged data to be stored + --------------------------------------------------------------------*/ + template + requires DocumentStorable + active::utility::Memory DocumentStoreEngine::mergeStore(const active::utility::Memory& toMerge) { + //Import the incoming records from the data to merge + Cache incoming; + Transport().receive(std::forward(incoming), active::serialise::Identity{}, toMerge); + //Get the data currently stored in the document + auto cache = getCache(); + if (!cache) + cache = std::make_unique(); //We still want to export an empty cache object even if it contains no records + cache->merge(incoming); + return buildStore(); + } //DocumentStoreEngine::mergeStore + +} + +#endif //SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE diff --git a/SpeckleLib/Speckle/Environment/Addon.cpp b/SpeckleLib/Speckle/Environment/Addon.cpp index 99a360c..015e643 100644 --- a/SpeckleLib/Speckle/Environment/Addon.cpp +++ b/SpeckleLib/Speckle/Environment/Addon.cpp @@ -46,11 +46,27 @@ String Addon::getLocalString(short itemIndex, short resourceIndex) const { RSGetIndString(&string, itemIndex, resourceIndex, ACAPI_GetOwnResModule()); return string; #else - return String{} + return String{}; #endif } //Addon::getLocalString +/*-------------------------------------------------------------------- + Determine if the active document is shared (in collaborative environments) + + return: True if the active document is shared + --------------------------------------------------------------------*/ +bool Addon::isSharedDocument() const { +#ifdef ARCHICAD + API_ProjectInfo pi{}; + ACAPI_ProjectOperation_Project(&pi); + return pi.teamwork; +#else + return false; +#endif +} //Addon::isSharedDocument + + /*-------------------------------------------------------------------- Publish an event from an external source to subscribers diff --git a/SpeckleLib/Speckle/Environment/Addon.h b/SpeckleLib/Speckle/Environment/Addon.h index 476ae98..7f52e71 100644 --- a/SpeckleLib/Speckle/Environment/Addon.h +++ b/SpeckleLib/Speckle/Environment/Addon.h @@ -38,6 +38,11 @@ namespace speckle::environment { @return The localised string */ speckle::utility::String getLocalString(short itemIndex, short resourceIndex) const; + /*! + Determine if the active document is shared (in collaborative environments) + @return True if the active document is shared + */ + bool isSharedDocument() const; // MARK: - Functions (mutating) diff --git a/SpeckleLib/Speckle/Interface/Browser/JSPortal.h b/SpeckleLib/Speckle/Interface/Browser/JSPortal.h index b610291..14bcc26 100644 --- a/SpeckleLib/Speckle/Interface/Browser/JSPortal.h +++ b/SpeckleLib/Speckle/Interface/Browser/JSPortal.h @@ -102,8 +102,8 @@ namespace speckle::interfac::browser { --------------------------------------------------------------------*/ template bool JSPortal::install(std::shared_ptr> object) { -#ifdef ARCHICAD try { +#ifdef ARCHICAD auto engine = getJSEngine(); if (!engine) return false; @@ -127,10 +127,10 @@ namespace speckle::interfac::browser { object->setPortal(*this); return true; } +#endif } catch(...) { ///TODO: Need to discuss the best course of action to notify of a failure } -#endif return false; } //JSPortal::install diff --git a/SpeckleLib/Speckle/Utility/Guid.h b/SpeckleLib/Speckle/Utility/Guid.h index b94b5c9..87de071 100644 --- a/SpeckleLib/Speckle/Utility/Guid.h +++ b/SpeckleLib/Speckle/Utility/Guid.h @@ -22,6 +22,12 @@ namespace speckle::utility { // MARK: - Constructors using base::base; + + /*! + Constructor + @param source The guid to copy + */ + Guid(const active::utility::Guid& source) : base{source} {} #ifdef ARCHICAD /*! diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj index b47d85c..f6d024e 100644 --- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj +++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj @@ -37,6 +37,9 @@ 21D0BD562C890B1C0077E104 /* ServerMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD542C890B1C0077E104 /* ServerMigration.h */; }; 21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD572C8910400077E104 /* UserInfo.cpp */; }; 21D0BD5A2C8910400077E104 /* UserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD582C8910400077E104 /* UserInfo.h */; }; + 21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */; }; + 21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */; }; + 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */; }; 21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F382C6B880B008B6A06 /* JSBaseTransport.cpp */; }; 21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */; }; 21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F602C6D0286008B6A06 /* GetBindingsMethodNames.cpp */; }; @@ -132,6 +135,9 @@ 21D0BD542C890B1C0077E104 /* ServerMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerMigration.h; sourceTree = ""; }; 21D0BD572C8910400077E104 /* UserInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserInfo.cpp; sourceTree = ""; }; 21D0BD582C8910400077E104 /* UserInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInfo.h; sourceTree = ""; }; + 21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentStoreCore.cpp; sourceTree = ""; }; + 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreCore.h; sourceTree = ""; }; + 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreEngine.h; sourceTree = ""; }; 21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = ""; }; 21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = ""; }; 21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = ""; }; @@ -293,8 +299,9 @@ children = ( 21D0BD1D2C86F0280077E104 /* AccountDatabase.cpp */, 21D0BD1E2C86F0280077E104 /* AccountDatabase.h */, - 21D0BD302C86FE090077E104 /* Identity */, 21D0BD272C86FC350077E104 /* Content */, + 21D0BD302C86FE090077E104 /* Identity */, + 21D0BDB02C8F8AB60077E104 /* Storage */, ); path = Database; sourceTree = ""; @@ -318,6 +325,24 @@ path = Identity; sourceTree = ""; }; + 21D0BDAF2C8F8AB60077E104 /* DocumentStore */ = { + isa = PBXGroup; + children = ( + 21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */, + 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */, + 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */, + ); + path = DocumentStore; + sourceTree = ""; + }; + 21D0BDB02C8F8AB60077E104 /* Storage */ = { + isa = PBXGroup; + children = ( + 21D0BDAF2C8F8AB60077E104 /* DocumentStore */, + ); + path = Storage; + sourceTree = ""; + }; 21F69F1A2C6A0FE2008B6A06 /* Browser */ = { isa = PBXGroup; children = ( @@ -447,8 +472,10 @@ 210CC88F2C81A98500610F58 /* Guid64.h in Headers */, 21B67D002C7CE15100FD64FC /* Exception.h in Headers */, 21D0BD2C2C86FC350077E104 /* Record.h in Headers */, + 21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */, 210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */, 21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */, + 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */, 2193518C2C62655700E5A69C /* MenuEvent.h in Headers */, 21D0BD312C86FE090077E104 /* Index.h in Headers */, ); @@ -581,6 +608,7 @@ 21F69F812C6FF3B0008B6A06 /* BridgeArgumentWrap.cpp in Sources */, 2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */, 21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */, + 21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */, 21F93AEC2B2F406E009A2C5B /* Addon.cpp in Sources */, 21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */, 21B67D0E2C7E0E8D00FD64FC /* ErrorReport.cpp in Sources */, From 53dd72989aba8dedb01187c99fc73abe4fc74b79 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Tue, 10 Sep 2024 23:35:12 +0100 Subject: [PATCH 03/16] Added DocStoreSubscriber Added DocStoreMergeEvent DocumentStoreCore now handles merge events Fixes to SelectionSubscriber --- .../DocumentStore/DocumentStoreCore.cpp | 45 ++++++++-- .../Storage/DocumentStore/DocumentStoreCore.h | 15 +++- .../DocumentStore/DocumentStoreEngine.h | 5 +- .../Event/Subscriber/DocStoreSubscriber.cpp | 88 +++++++++++++++++++ .../Event/Subscriber/DocStoreSubscriber.h | 74 ++++++++++++++++ .../Event/Subscriber/SelectionSubscriber.cpp | 10 +++ .../Event/Subscriber/SelectionSubscriber.h | 8 +- .../Speckle/Event/Type/DocStoreMergeEvent.h | 43 +++++++++ .../SpeckleLib.xcodeproj/project.pbxproj | 10 +++ 9 files changed, 281 insertions(+), 17 deletions(-) create mode 100644 SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp create mode 100644 SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h create mode 100644 SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp index 36cbee2..af6658d 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -3,6 +3,7 @@ #include "Active/Utility/Memory.h" #include "Active/Utility/String.h" #include "Speckle/Environment/Addon.h" +#include "Speckle/Event/Type/DocStoreMergeEvent.h" #include "Speckle/Utility/Guid.h" #include "Speckle/Utility/String.h" @@ -14,6 +15,7 @@ using namespace active::setting; using namespace speckle::database; using namespace speckle::environment; +using namespace speckle::event; using namespace speckle::utility; using enum DocumentStoreCore::Status; @@ -55,16 +57,27 @@ namespace { if (storeID.id) return true; //We must have a store if the ID is populated bool isStoreFound = false; -#ifdef ARCHICAD API_Guid acID; if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectGuidFromName(String{storeID.name}, &acID)); statusCode != nominal) throw std::system_error(DocumentStoreCore::makeError(statusCode)); storeID.id = Guid{acID}; isStoreFound = true; -#endif return isStoreFound; } //isExistingStore + + /*-------------------------------------------------------------------- + Copy a GS handle to a Memory object + + handle: The GS handle + memory: The Memory object to receive the data + --------------------------------------------------------------------*/ + void copyHandleToMemory(const GSHandle& handle, active::utility::Memory& memory) { + auto storeSize = BMGetHandleSize(handle); + memory.resize(storeSize); + active::utility::Memory::copy(memory.data(), *handle, storeSize, storeSize); + } //copyHandleToMemory + #endif ///Category for DocumentStore processing errors @@ -111,6 +124,30 @@ std::error_code DocumentStoreCore::makeError(DocumentStoreCore::Status code) { } //DocumentStoreCore::makeError +/*-------------------------------------------------------------------- + Handle a document merge operation + + event: The merge event + + return: True if the event should be closed + --------------------------------------------------------------------*/ +bool DocumentStoreCore::handle(const DocStoreMergeEvent& event) { +#ifdef ARCHICAD + if (event.objects == nullptr) + return false; + for (const auto& object : *event.objects) { + if (*object.name != String{m_id.name}) + continue; + active::utility::Memory toMerge; + copyHandleToMemory(object.data, toMerge); + mergeStore(toMerge); + writeStore(); + } +#endif + return false; +} //DocumentStoreCore::handle + + /*-------------------------------------------------------------------- Read the data stored in the document @@ -128,9 +165,7 @@ active::utility::Memory DocumentStoreCore::readStore() const { if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectContent(Guid{m_id.id}, &storeName, &storedData)); statusCode != nominal) throw std::system_error(makeError(statusCode)); //Copy the stored data into the result - auto storeSize = BMGetHandleSize(storedData); - result.resize(storeSize); - active::utility::Memory::copy(result.data(), *storedData, storeSize, storeSize); + copyHandleToMemory(storedData, result); BMKillHandle(&storedData); #endif return result; diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h index 7a81aa1..57933d1 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h @@ -5,6 +5,7 @@ #include "Active/Setting/SettingList.h" #include "Active/Database/Storage/DBaseSchema.h" #include "Active/Utility/NameID.h" +#include "Speckle/Event/Subscriber/DocStoreSubscriber.h" namespace speckle::database { @@ -13,7 +14,7 @@ namespace speckle::database { Currently implement for Archicad Add-On Objects */ - class DocumentStoreCore { + class DocumentStoreCore : public event::DocStoreSubscriber { public: // MARK: - Types @@ -54,6 +55,15 @@ namespace speckle::database { */ const active::utility::NameID& getID() const { return m_id; } + // MARK: - Functions (mutating) + + /*! + Handle a document merge operation + @param event The merge event + @return True if the event should be closed + */ + bool handle(const event::DocStoreMergeEvent& event) override; + protected: /*! Read the data stored in the document (should be lazy-loading, only at the point where data is actually requested) @@ -73,9 +83,8 @@ namespace speckle::database { /*! Merge existing stored data with incoming stored data (from an external source) @param toMerge The external stored data to merge - @return The merged data to be stored */ - virtual active::utility::Memory mergeStore(const active::utility::Memory& toMerge) = 0; + virtual void mergeStore(const active::utility::Memory& toMerge) = 0; /*! Reset the stored data (some external change has invalidated previous data, e.g. the document was closed) */ diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index 663d8ab..9231487 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -120,7 +120,7 @@ namespace speckle::database { @param toMerge The external stored data to merge @return The merged data to be stored */ - active::utility::Memory mergeStore(const active::utility::Memory& toMerge) override; + void mergeStore(const active::utility::Memory& toMerge) override; /*! Reset the stored data (some external change has invalidated previous data, e.g. the document was closed) */ @@ -266,7 +266,7 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - active::utility::Memory DocumentStoreEngine::mergeStore(const active::utility::Memory& toMerge) { + void DocumentStoreEngine::mergeStore(const active::utility::Memory& toMerge) { //Import the incoming records from the data to merge Cache incoming; Transport().receive(std::forward(incoming), active::serialise::Identity{}, toMerge); @@ -275,7 +275,6 @@ namespace speckle::database { if (!cache) cache = std::make_unique(); //We still want to export an empty cache object even if it contains no records cache->merge(incoming); - return buildStore(); } //DocumentStoreEngine::mergeStore } diff --git a/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp new file mode 100644 index 0000000..00704da --- /dev/null +++ b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp @@ -0,0 +1,88 @@ +#include "Speckle/Event/Subscriber/DocStoreSubscriber.h" + +#include "Speckle/Environment/Addon.h" +#include "Speckle/Database/Identity/Link.h" +#include "Speckle/Event/Type/DocStoreMergeEvent.h" + +#ifdef ARCHICAD +#include +#endif + +using namespace active::environment; +using namespace active::event; +using namespace speckle::database; +using namespace speckle::environment; +using namespace speckle::event; + +namespace { + +#ifdef ARCHICAD + /*! + Callback for an Archicad document merge operation + @param sourceObjects The source document objects to merge + */ + GSErrCode __ACENV_CALL docMergeCallback(const GS::Array& sourceObjects) { + if (addon() != nullptr) + addon()->publishExternal(DocStoreMergeEvent{sourceObjects}); + return NoError; + } +#endif + +} + + //True if a doc merge subscriber has already started (only one is required - there are no variants) +bool speckle::event::DocStoreSubscriber::m_isStarted = false; + +/*-------------------------------------------------------------------- + Get the event subscription list + + return: The subscription list (an empty list will put the subscriber into a suspended state) + --------------------------------------------------------------------*/ +Subscriber::Subscription DocStoreSubscriber::subscription() const { + return { {DocStoreMergeEvent::ID} }; +} //DocStoreSubscriber::subscription + + +/*-------------------------------------------------------------------- + Receive a subscribed event + + event: The incoming event + + return: True if the event should be closed + --------------------------------------------------------------------*/ +bool DocStoreSubscriber::receive(const Event& event) { + //Pass a menu event to the specified handler function + if (auto selectEvent = dynamic_cast(&event); selectEvent != nullptr) + return handle(*selectEvent); + return false; +} //DocStoreSubscriber::receive + + +/*-------------------------------------------------------------------- + Attach participant components to the app (as required) + + return: True if the participant is able to function + --------------------------------------------------------------------*/ +bool DocStoreSubscriber::attach() { +#ifdef ARCHICAD + ACAPI_AddOnObject_RegisterAddOnObjectHandler(); +#endif + return true; +} //DocStoreSubscriber::attach + + +/*-------------------------------------------------------------------- + Start the participant operation + + return: True if the participant is able to continue + --------------------------------------------------------------------*/ +bool DocStoreSubscriber::start() { + if (m_isStarted) + return true; + m_isStarted = true; +#ifdef ARCHICAD + return (ACAPI_AddOnObject_InstallAddOnObjectMergeHandler(docMergeCallback) == NoError); +#else + return false; +#endif +} //DocStoreSubscriber::start diff --git a/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h new file mode 100644 index 0000000..d14e84c --- /dev/null +++ b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h @@ -0,0 +1,74 @@ +#ifndef SPECKLE_EVENT_DOC_STORE_SUBSCRIBER +#define SPECKLE_EVENT_DOC_STORE_SUBSCRIBER + +#include "Active/Event/Subscriber.h" + +namespace speckle::event { + + class DocStoreMergeEvent; + + /*! + Base class for subscribers responding to document merge operations (notably those managing custom data in the document) + */ + class DocStoreSubscriber : public active::event::Subscriber { + public: + + // MARK: - Constructors + + /*! + Default constructor + */ + DocStoreSubscriber() = default; + /*! + Copy constructor + @param source The object to copy + */ + DocStoreSubscriber(const DocStoreSubscriber& source) = default; + /*! + Destructor + */ + virtual ~DocStoreSubscriber() {} + + // MARK: - Functions (const) + + /*! + Get the event subscription list + @return The subscription list (an empty list will put the subscriber into a suspended state) + */ + Subscription subscription() const override; + + // MARK: - Functions (mutating) + + /*! + Receive a subscribed event + @param event The incoming event + @return True if the event should be closed + */ + bool receive(const active::event::Event& event) override; + + protected: + /*! + Attach participant components to the app (as required) + @return True if the participant is able to function + */ + bool attach() override; + /*! + Start the participant operation + @return True if the participant is able to continue + */ + bool start() override; + /*! + Handle a document merge operation + @param event The merge event + @return True if the event should be closed + */ + virtual bool handle(const DocStoreMergeEvent& event) = 0; + + private: + ///True if a doc merge subscriber has already started (only one is required - there are no variants) + static bool m_isStarted; + }; + +} + +#endif //SPECKLE_EVENT_DOC_STORE_SUBSCRIBER diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp index 955c265..576b4df 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp +++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp @@ -4,6 +4,10 @@ #include "Speckle/Database/Identity/Link.h" #include "Speckle/Event/Type/SelectionEvent.h" +#ifdef ARCHICAD +#include +#endif + using namespace active::environment; using namespace active::event; using namespace speckle::database; @@ -28,6 +32,9 @@ namespace { } + //True if a selection change subscriber has already started (only one is required - there are no variants) +bool speckle::event::SelectionSubscriber::m_isStarted = false; + /*-------------------------------------------------------------------- Get the event subscription list @@ -59,6 +66,9 @@ bool SelectionSubscriber::receive(const Event& event) { return: True if the participant is able to continue --------------------------------------------------------------------*/ bool SelectionSubscriber::start() { + if (m_isStarted) + return true; + m_isStarted = true; #ifdef ARCHICAD return (ACAPI_Notification_CatchSelectionChange(selectionCallback) == NoError); #else diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h index 199184f..56314dd 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h +++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h @@ -3,16 +3,12 @@ #include "Active/Event/Subscriber.h" -#ifdef ARCHICAD -#include -#endif - namespace speckle::event { class SelectionEvent; /*! - Base class for subscribers responding to selectionm changes + Base class for subscribers responding to selection changes */ class SelectionSubscriber : public active::event::Subscriber { public: @@ -65,7 +61,7 @@ namespace speckle::event { private: ///True if a selection change subscriber has already started (only one is required - there are no variants) - int32_t m_isStarted = false; + static bool m_isStarted; }; } diff --git a/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h b/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h new file mode 100644 index 0000000..e944c5a --- /dev/null +++ b/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h @@ -0,0 +1,43 @@ +#ifndef SPECKLE_EVENT_DOC_STORE_MERGE_EVENT +#define SPECKLE_EVENT_DOC_STORE_MERGE_EVENT + +#include "Active/Event/Event.h" + +#include "Active/Utility/Guid.h" +#include "Active/Utility/String.h" +#include "Speckle/Database/Identity/Link.h" + +namespace speckle::event { + + /*! + Class representing a selection change event + */ + class DocStoreMergeEvent : public active::event::Event { + public: + + static const inline active::utility::NameID ID{active::utility::String{"document store merge"}, + active::utility::Guid{active::utility::String{"c92e2c51-d47c-44e3-a54f-5068dccaa35a"}}}; + + // MARK: - Constructors + + /*! + Default constructor + */ + DocStoreMergeEvent() : Event{ID} {} +#ifdef ARCHICAD + /*! + Constructor + @param incoming Incoming document objects to merge + */ + DocStoreMergeEvent(const GS::Array& incoming) : Event{ID} { objects = &incoming; } +#endif + +#ifdef ARCHICAD + //Incoming document objects to merge + const GS::Array* objects = nullptr; +#endif + }; + +} + +#endif //SPECKLE_EVENT_DOC_STORE_MERGE_EVENT diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj index f6d024e..0846643 100644 --- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj +++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */; }; 21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */; }; 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */; }; + 21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */; }; + 21D0BDBF2C90F36B0077E104 /* DocStoreMergeEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */; }; 21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F382C6B880B008B6A06 /* JSBaseTransport.cpp */; }; 21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */; }; 21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F602C6D0286008B6A06 /* GetBindingsMethodNames.cpp */; }; @@ -138,6 +140,9 @@ 21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentStoreCore.cpp; sourceTree = ""; }; 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreCore.h; sourceTree = ""; }; 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreEngine.h; sourceTree = ""; }; + 21D0BDBA2C90F2830077E104 /* DocStoreSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocStoreSubscriber.h; sourceTree = ""; }; + 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocStoreSubscriber.cpp; sourceTree = ""; }; + 21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocStoreMergeEvent.h; sourceTree = ""; }; 21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = ""; }; 21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = ""; }; 21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = ""; }; @@ -254,6 +259,8 @@ 2193517A2C624FC100E5A69C /* Subscriber */ = { isa = PBXGroup; children = ( + 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */, + 21D0BDBA2C90F2830077E104 /* DocStoreSubscriber.h */, 219351782C624FC100E5A69C /* MenuSubscriber.cpp */, 219351792C624FC100E5A69C /* MenuSubscriber.h */, 219351992C6278D900E5A69C /* SelectionSubscriber.cpp */, @@ -265,6 +272,7 @@ 2193518A2C62655700E5A69C /* Type */ = { isa = PBXGroup; children = ( + 21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */, 219351892C62655700E5A69C /* MenuEvent.h */, 2193519C2C627E3100E5A69C /* SelectionEvent.h */, ); @@ -462,6 +470,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 21D0BDBF2C90F36B0077E104 /* DocStoreMergeEvent.h in Headers */, 21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */, 210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */, 210CC8A02C81E34400610F58 /* Platform.h in Headers */, @@ -608,6 +617,7 @@ 21F69F812C6FF3B0008B6A06 /* BridgeArgumentWrap.cpp in Sources */, 2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */, 21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */, + 21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */, 21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */, 21F93AEC2B2F406E009A2C5B /* Addon.cpp in Sources */, 21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */, From d00c20f0c6f0d4f150997cad011a785161268ef6 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Wed, 11 Sep 2024 23:11:40 +0100 Subject: [PATCH 04/16] ModelCardDatabase subscribes to project/merge events ModelCardDatabase can be serialised as required for GetDocumentState method Added ProjectSubscriber Added ProjectEvent --- SpeckleConnector/Connector/Connector.cpp | 1 + .../Database/Model/Card/ModelCard.cpp | 11 +- .../Connector/Database/Model/Card/ModelCard.h | 12 +- .../Database/Model/Card/ModelCardDatabase.cpp | 109 +++++++++-------- .../Database/Model/Card/ModelCardDatabase.h | 64 +++++----- .../Browser/Bridge/Base/GetDocumentState.cpp | 12 +- SpeckleLib/Speckle/Database/Content/Record.h | 8 +- .../DocumentStore/DocumentStoreCore.cpp | 25 ++++ .../Storage/DocumentStore/DocumentStoreCore.h | 22 +++- .../DocumentStore/DocumentStoreEngine.h | 114 +++++++++--------- .../Event/Subscriber/DocStoreSubscriber.cpp | 4 +- .../Event/Subscriber/ProjectSubscriber.cpp | 76 ++++++++++++ .../Event/Subscriber/ProjectSubscriber.h | 69 +++++++++++ .../Speckle/Event/Type/DocStoreMergeEvent.h | 3 +- SpeckleLib/Speckle/Event/Type/ProjectEvent.h | 58 +++++++++ .../Speckle/Record/Credentials/Account.cpp | 1 + .../SpeckleLib.xcodeproj/project.pbxproj | 14 ++- 17 files changed, 434 insertions(+), 169 deletions(-) create mode 100644 SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.cpp create mode 100644 SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h create mode 100644 SpeckleLib/Speckle/Event/Type/ProjectEvent.h diff --git a/SpeckleConnector/Connector/Connector.cpp b/SpeckleConnector/Connector/Connector.cpp index 89ce861..09489cd 100755 --- a/SpeckleConnector/Connector/Connector.cpp +++ b/SpeckleConnector/Connector/Connector.cpp @@ -29,6 +29,7 @@ namespace { ConnectorInstance(const String& name) : ConnectorAddon{name} { add(); add(); + addWeak(m_modelCards.getSubscription()); } // MARK: Functions (const) diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp index d6030d0..17ae829 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp @@ -14,7 +14,6 @@ namespace { ///Serialisation fields enum FieldIndex { - idID, modelID, projectID, accountID, @@ -24,7 +23,6 @@ namespace { ///Serialisation field IDs static std::array fieldID = { - Identity{"id"}, Identity{"modelId"}, Identity{"projectId"}, Identity{"accountId"}, @@ -45,7 +43,6 @@ bool ModelCard::fillInventory(Inventory& inventory) const { using enum Entry::Type; inventory.merge(Inventory{ { - { fieldID[idID], idID, element }, { fieldID[modelID], modelID, element }, { fieldID[projectID], projectID, element }, { fieldID[accountID], accountID, element }, @@ -53,7 +50,7 @@ bool ModelCard::fillInventory(Inventory& inventory) const { { fieldID[settingsID], settingsID, element }, }, }.withType(&typeid(ModelCard))); - return true; + return base::fillInventory(inventory); } //ModelCard::fillInventory @@ -66,11 +63,9 @@ bool ModelCard::fillInventory(Inventory& inventory) const { --------------------------------------------------------------------*/ Cargo::Unique ModelCard::getCargo(const Inventory::Item& item) const { if (item.ownerType != &typeid(ModelCard)) - return nullptr; + return base::getCargo(item); using namespace active::serialise; switch (item.index) { - case idID: - return std::make_unique>(m_ID); case modelID: return std::make_unique>(m_modelID); case projectID: @@ -91,7 +86,7 @@ Cargo::Unique ModelCard::getCargo(const Inventory::Item& item) const { Set to the default package content --------------------------------------------------------------------*/ void ModelCard::setDefault() { - m_ID.clear(); + base::setDefault(); m_modelID.clear(); m_projectID.clear(); m_accountID.clear(); diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h index 23339f8..d0d249e 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h @@ -6,18 +6,19 @@ #include "Active/Utility/Cloner.h" #include "Connector/Database/Model/Card/CardSetting.h" #include "Speckle/Utility/String.h" +#include "Speckle/Database/Content/Record.h" namespace connector::database { /*! A connector send filter */ - class ModelCard : public active::serialise::Package, public active::utility::Cloner { + class ModelCard : public speckle::database::Record { public: // MARK: - Types - using base = active::serialise::Package; + using base = speckle::database::Record; //List of card settings using SettingList = active::container::Vector; @@ -35,11 +36,6 @@ namespace connector::database { // MARK: - Functions (const) - /*! - Get the card ID - @return The card ID - */ - const speckle::utility::String& getID() const { return m_ID; } /*! Get the model ID @return The model ID @@ -86,8 +82,6 @@ namespace connector::database { void setDefault() override; private: - ///A unique ID for the card (not the ID of the linked model) - speckle::utility::String m_ID; ///The model ID speckle::utility::String m_modelID; ///The project ID diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp index 701a473..264af71 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp @@ -1,71 +1,86 @@ #include "Connector/Database/Model/Card/ModelCardDatabase.h" -#include "Active/Serialise/CargoHold.h" -#include "Active/Serialise/Item/Wrapper/ValueWrap.h" -#include "Active/Serialise/Package/Wrapper/ValueSettingWrap.h" -#include "Active/Setting/ValueSetting.h" +#include "Active/Database/Storage/Storage.h" +#include "Active/Serialise/JSON/JSONTransport.h" +#include "Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h" #include +using namespace active::container; +using namespace active::database; using namespace active::serialise; +using namespace active::serialise::json; using namespace active::setting; using namespace connector::database; +using namespace speckle::database; using namespace speckle::utility; +namespace connector::database { + + ///ModelCard database engine declaration + using ModelCardEngine = DocumentStoreEngine; + + ///ModelCard database storage declaration + class ModelCardDatabase::Store : public active::database::Storage { + using base = active::database::Storage; + using base::base; + }; + +} + namespace { - - ///Serialisation fields - enum FieldIndex { - model, - }; - - ///Serialisation field IDs - static std::array fieldID = { - Identity{"models"}, - }; + + ///The document storage identifier for model cards + const char* modelCardDBaseName = "connector::database::ModelModelCardDatabase"; + ///The document storage identifier for model cards + const char* modelCardTableName = "models"; } /*-------------------------------------------------------------------- - Fill an inventory with the package items - - inventory: The inventory to receive the package items - - return: True if the package has added items to the inventory + Constructor --------------------------------------------------------------------*/ -bool ModelCardDatabase::fillInventory(Inventory& inventory) const { - using enum Entry::Type; - inventory.merge(Inventory{ - { - { fieldID[model], model, element }, - }, - }.withType(&typeid(ModelCardDatabase))); - return true; -} //ModelCardDatabase::fillInventory +ModelCardDatabase::ModelCardDatabase() { + + auto engine = std::make_shared(modelCardDBaseName, + //Schema + DBaseSchema{active::utility::String{modelCardDBaseName}, + //Tables + { + //Model card table + { + modelCardTableName, 0, 0, {} //The table specifics aren't relevant in this context + } + } + } + ); + m_store = std::make_unique(std::move(engine)); +} //ModelCardDatabase::ModelCardDatabase /*-------------------------------------------------------------------- - Get the specified cargo - - item: The inventory item to retrieve - - return: The requested cargo (nullptr on failure) + Destructor --------------------------------------------------------------------*/ -Cargo::Unique ModelCardDatabase::getCargo(const Inventory::Item& item) const { - if (item.ownerType != &typeid(ModelCardDatabase)) - return nullptr; - using namespace active::serialise; - switch (item.index) { - case model: - return std::make_unique>(); //NB: This is a placeholder until we define the content - default: - return nullptr; //Requested an unknown index - } -} //ModelCardDatabase::getCargo +ModelCardDatabase::~ModelCardDatabase() {} /*-------------------------------------------------------------------- - Set to the default package content + Get all model cards + + return: All the cards --------------------------------------------------------------------*/ -void ModelCardDatabase::setDefault() { -} //ModelCardDatabase::setDefault +Vector ModelCardDatabase::getCards() const { + return m_store->getObjects(); +} //ModelCardDatabase::getCards + + +/*-------------------------------------------------------------------- + Get a serialisation wrapper for the database + + return: A database wrapper + --------------------------------------------------------------------*/ +std::unique_ptr ModelCardDatabase::wrapper() const { + return m_store->wrapper(); +} //ModelCardDatabase::wrapper diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h index 39a61f3..4d452be 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h @@ -1,56 +1,56 @@ #ifndef CONNECTOR_DATABASE_MODEL_CARD_DATABASE #define CONNECTOR_DATABASE_MODEL_CARD_DATABASE -#include "Active/Serialise/Package/Package.h" -#include "Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h" -#include "Speckle/Utility/String.h" +#include "Connector/Database/Model/Card/ModelCard.h" + +namespace active::event { + class Subscriber; +} namespace connector::database { /*! Database of model cards relating to a specific project */ - class ModelCardDatabase : public active::serialise::Package { + class ModelCardDatabase { public: - // MARK: - Types - - using base = active::serialise::Package; - // MARK: - Constructors /*! - Default constructor + Constructor */ - ModelCardDatabase() {} + ModelCardDatabase(); + ModelCardDatabase(const ModelCardDatabase&) = delete; + /*! + Destructor + */ + ~ModelCardDatabase(); - // MARK: - Public variables (NB: Assuming to class invariants or overrides for this data, so making public for simplicity) - - - // MARK: Functions (const) - - //Implement card access when necessary - - // MARK: - Serialisation + // MARK: - Functions (const) /*! - Fill an inventory with the package items - @param inventory The inventory to receive the package items - @return True if the package has added items to the inventory - */ - bool fillInventory(active::serialise::Inventory& inventory) const override; + Get all model cards + @return All the cards + */ + active::container::Vector getCards() const; /*! - Get the specified cargo - @param item The inventory item to retrieve - @return The requested cargo (nullptr on failure) - */ - Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + Get a serialisation wrapper for the database + @return A database wrapper + */ + std::unique_ptr wrapper() const; /*! - Set to the default package content - */ - void setDefault() override; + Get the database subscription (the content is document-based, and must react to document operations) + @return The database subscription (add weakly to publisher) + */ + std::shared_ptr getSubscription() const; + + // MARK: - Functions (mutating) + private: - //TODO: Model card array here - implement when necessary + class Store; + ///Model card database storage + std::shared_ptr m_store; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp index 5353a37..beccf4e 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp @@ -1,6 +1,9 @@ #include "Connector/Interface/Browser/Bridge/Base/GetDocumentState.h" #include "Active/Serialise/CargoHold.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Connector/Connector.h" +#include "Connector/Database/Model/Card/ModelCard.h" #include "Connector/Database/Model/Card/ModelCardDatabase.h" using namespace active::container; @@ -11,7 +14,7 @@ using namespace speckle::utility; namespace { - using WrappedValue = active::serialise::CargoHold; + using WrappedValue = active::serialise::CargoHold, Vector>; } @@ -29,7 +32,8 @@ GetDocumentState::GetDocumentState() : BridgeMethod{"GetDocumentState", [&]() { return: The document info --------------------------------------------------------------------*/ std::unique_ptr GetDocumentState::run() const { - ///TODO: Retrieve the model card database from connector()->getModelCards() in future (when implemented) - ModelCardDatabase modelCards; //This is just a temp so something can be sent back to the JS for the interim - return std::make_unique(modelCards); + if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) { + return modelCardDBase->wrapper(); + } + return nullptr; } //GetDocumentState::run diff --git a/SpeckleLib/Speckle/Database/Content/Record.h b/SpeckleLib/Speckle/Database/Content/Record.h index 2c9c089..6a99d6e 100644 --- a/SpeckleLib/Speckle/Database/Content/Record.h +++ b/SpeckleLib/Speckle/Database/Content/Record.h @@ -9,12 +9,12 @@ namespace speckle::database { /*! Base class for a database record */ - class Record : public active::database::Record { + class Record : public active::database::Record { public: // MARK: - Types - using base = active::database::Record; + using base = active::database::Record; ///Unique pointer using Unique = std::unique_ptr; ///Shared pointer @@ -24,6 +24,10 @@ namespace speckle::database { // MARK: - Constructors + /*! + Default constructor + */ + Record() : base{} {} /*! Constructor @param ID The record ID diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp index af6658d..6456818 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -4,6 +4,7 @@ #include "Active/Utility/String.h" #include "Speckle/Environment/Addon.h" #include "Speckle/Event/Type/DocStoreMergeEvent.h" +#include "Speckle/Event/Type/ProjectEvent.h" #include "Speckle/Utility/Guid.h" #include "Speckle/Utility/String.h" @@ -148,6 +149,30 @@ bool DocumentStoreCore::handle(const DocStoreMergeEvent& event) { } //DocumentStoreCore::handle +/*-------------------------------------------------------------------- + Handle a project event + + event: The project event + + return: True if the event should be closed + --------------------------------------------------------------------*/ +bool DocumentStoreCore::handle(const event::ProjectEvent& event) { +#ifdef ARCHICAD + switch (event.getType()) { + case APINotify_Close: + resetStore(); //Wipe the cache, forcing a full reload when the data is requested again (after a project is opened) + break; + case APINotify_PreSave: case APINotify_SendChanges: + writeStore(); //Ensure the data is stored with the save/send + break; + default: + break; + } +#endif + return false; +} //DocumentStoreCore::handle + + /*-------------------------------------------------------------------- Read the data stored in the document diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h index 57933d1..450d207 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h @@ -6,15 +6,18 @@ #include "Active/Database/Storage/DBaseSchema.h" #include "Active/Utility/NameID.h" #include "Speckle/Event/Subscriber/DocStoreSubscriber.h" +#include "Speckle/Event/Subscriber/ProjectSubscriber.h" namespace speckle::database { + using DocumentStoreSchema = active::database::DBaseSchema<>; + /*! Core functionality and definitions for a mechanism to store data in a BIM (3rd-party) document/database Currently implement for Archicad Add-On Objects */ - class DocumentStoreCore : public event::DocStoreSubscriber { + class DocumentStoreCore : public event::DocStoreSubscriber, public event::ProjectSubscriber { public: // MARK: - Types @@ -40,8 +43,10 @@ namespace speckle::database { /*! Default constructor @param id The document storage identifier + @param schema The document storage schema */ - DocumentStoreCore(const active::utility::NameID& id) : m_id(id) {} + DocumentStoreCore(const active::utility::NameID& id, DocumentStoreSchema&& schema) : m_id(id), m_schema{schema} {} + DocumentStoreCore(const DocumentStoreCore&) = default; /*! Destructor */ @@ -49,6 +54,11 @@ namespace speckle::database { // MARK: - Function (const) + /*! + Get the database schema + @return The database schema + */ + const DocumentStoreSchema& getSchema() const { return m_schema; } /*! Get the database id @return The database id @@ -63,6 +73,12 @@ namespace speckle::database { @return True if the event should be closed */ bool handle(const event::DocStoreMergeEvent& event) override; + /*! + Handle a project event + @param event The project event + @return True if the event should be closed + */ + bool handle(const event::ProjectEvent& event) override; protected: /*! @@ -91,6 +107,8 @@ namespace speckle::database { virtual void resetStore() = 0; private: + ///The database schema + DocumentStoreSchema m_schema; ///The database ID (mutable to allow lazy loading when data is accessed) mutable active::utility::NameID m_id; }; diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index 9231487..6f7de19 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -9,6 +9,7 @@ #include "Active/Serialise/Package/Wrapper/PackageWrap.h" #include "Active/Serialise/Transport.h" #include "Active/Utility/BufferIn.h" +#include "Active/Utility/BufferOut.h" #include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h" #include "Speckle/Utility/Guid.h" #include "Speckle/Utility/String.h" @@ -32,16 +33,17 @@ namespace speckle::database { @tparam Transport The serialisation transport mechanism for objects @tparam ObjID The object identifier type, e.g. Guid */ - template + template requires DocumentStorable - class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { + class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { public: // MARK: - Types - using base = active::database::DBaseEngine; + using base = active::database::DBaseEngine; using Filter = base::Filter; - using Cache = active::database::RecordCache; + using Outline = base::Outline; + using Cache = active::database::RecordCache; // MARK: - Constructors @@ -49,19 +51,8 @@ namespace speckle::database { Constructor @param id The document storage identifier */ - DocumentStoreEngine(const active::utility::NameID& id) : DocumentStoreCore{id} {} - /*! - Copy constructor - @param source The object to copy - */ - DocumentStoreEngine(const DocumentStoreEngine& source) : DocumentStoreCore{source}, base{source} { - m_cache = (source.m_cache) ? std::make_unique(*source.m_cache) : nullptr; - } - /*! - Object cloning - @return A clone of this object - */ - DocumentStoreEngine* clonePtr() const override { return new DocumentStoreEngine{*this}; } + DocumentStoreEngine(const active::utility::NameID& id, DocumentStoreSchema&& schema) : DocumentStoreCore{id, std::move(schema)} {} + DocumentStoreEngine(const DocumentStoreEngine&) = delete; // MARK: - Functions (const) @@ -72,14 +63,14 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) @return The requested object (nullptr on failure) */ - std::unique_ptr getObject(const ObjID& ID, utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + std::unique_ptr getObject(const ObjID& objID, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Get all objects @param tableID Optional table ID (defaults to the first table) @param documentID Optional document ID (filter for this document only - nullopt = all objects) @return The requested objects (nullptr on failure) */ - active::container::Vector getObjects(utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + active::container::Vector getObjects(std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Get a filtered list of objects @param filter The object filter @@ -87,8 +78,8 @@ namespace speckle::database { @param documentID Optional document ID (filter for this document only - nullopt = all objects) @return The filtered objects (nullptr on failure) */ - active::container::Vector getObjects(const Filter& filter, utility::String::Option tableID = std::nullopt, - utility::String::Option documentID = std::nullopt) const override; + active::container::Vector getObjects(const Filter& filter, std::optional tableID = std::nullopt, + std::optional documentID = std::nullopt) const override; /*! Erase an object by index @param ID The object ID @@ -96,14 +87,20 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) @throw Exception thrown on SQL error */ - void erase(const ObjID& ID, utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + void erase(const ObjID& ID, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Erase all objects @param tableID Optional table ID (defaults to the first table) @param documentID Optional document ID (when the object is bound to a specific document) @throw Exception thrown on SQL error */ - void erase(utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + void erase(std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; + /*! + Get the database outline + @return The database outline + */ + Outline getOutline() const override; + protected: /*! Get the cache of records built from the data stored in the document @@ -128,7 +125,7 @@ namespace speckle::database { private: //Cached records from the document store - std::unique_ptr m_cache; + mutable std::unique_ptr m_cache; }; /*-------------------------------------------------------------------- @@ -140,15 +137,15 @@ namespace speckle::database { requires DocumentStorable typename DocumentStoreEngine::Cache* DocumentStoreEngine::getCache() const { if (m_cache) - return m_cache; + return m_cache.get(); //Read the data stored in the document auto storedData = readStore(); m_cache = std::make_unique(); if (!storedData) - return m_cache; //Return an empty container if there's no data + return m_cache.get(); //Return an empty container if there's no data //Import the document data into the record cache Transport().receive(std::forward(*m_cache), active::serialise::Identity{}, storedData); - return m_cache; + return m_cache.get(); } //DocumentStoreEngine::getCache @@ -163,10 +160,9 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, utility::String::Option tableID, - utility::String::Option documentID) const { - auto cache = getCache(); - return cache ? cache->read(ID) : nullptr; + std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, std::optional tableID, + std::optional documentID) const { + return getCache()->read(ID); } //DocumentStoreEngine::getObject @@ -180,10 +176,9 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - active::container::Vector DocumentStoreEngine::getObjects(utility::String::Option tableID, - utility::String::Option documentID) const { - auto cache = getCache(); - return cache ? cache->read() : nullptr; + active::container::Vector DocumentStoreEngine::getObjects(std::optional tableID, + std::optional documentID) const { + return getCache()->read(); } //DocumentStoreEngine::getObjects @@ -198,10 +193,9 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, utility::String::Option tableID, - utility::String::Option documentID) const { - auto cache = getCache(); - return cache ? cache->read(filter) : nullptr; + active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, std::optional tableID, + std::optional documentID) const { + return getCache()->read(filter); } //DocumentStoreEngine::getObjects @@ -216,11 +210,9 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - void DocumentStoreEngine::erase(const ObjID& ID, utility::String::Option tableID, - utility::String::Option documentID) const { - auto cache = getCache(); - if (cache) - cache->erase(ID); + void DocumentStoreEngine::erase(const ObjID& ID, std::optional tableID, + std::optional documentID) const { + getCache()->erase(ID); } //DocumentStoreEngine::erase @@ -232,11 +224,26 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - void DocumentStoreEngine::erase(utility::String::Option tableID, utility::String::Option documentID) const { - auto cache = getCache(); - if (cache) - cache->erase(); + void DocumentStoreEngine::erase(std::optional tableID, std::optional documentID) const { + getCache()->erase(); } //DocumentStoreEngine::erase + + + /*-------------------------------------------------------------------- + Get the database outline + + return: The database outline + --------------------------------------------------------------------*/ + template + requires DocumentStorable + DocumentStoreEngine::Outline DocumentStoreEngine::getOutline() const { + Outline result; + if (getSchema().empty()) + return result; + //NB: Currently implementing only a single table in a document store + result.emplace_back(std::make_pair(getSchema()[0].ID, getCache()->keys())); + return result; + } //DocumentStoreEngine::getOutline /*-------------------------------------------------------------------- @@ -248,11 +255,7 @@ namespace speckle::database { requires DocumentStorable active::utility::Memory DocumentStoreEngine::buildStore() { active::utility::Memory result; - auto cache = getCache(); - if (!cache) - cache = std::make_unique(); //We still want to export an empty cache object even if it contains no records - //Export the cached records - Transport().send(std::forward(*m_cache), active::serialise::Identity{}, result); + Transport().send(std::forward(*getCache()), active::serialise::Identity{}, result); return result; } //DocumentStoreEngine::buildStore @@ -271,10 +274,7 @@ namespace speckle::database { Cache incoming; Transport().receive(std::forward(incoming), active::serialise::Identity{}, toMerge); //Get the data currently stored in the document - auto cache = getCache(); - if (!cache) - cache = std::make_unique(); //We still want to export an empty cache object even if it contains no records - cache->merge(incoming); + getCache()->merge(std::forward(incoming)); } //DocumentStoreEngine::mergeStore } diff --git a/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp index 00704da..34ca492 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp +++ b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.cpp @@ -52,8 +52,8 @@ Subscriber::Subscription DocStoreSubscriber::subscription() const { --------------------------------------------------------------------*/ bool DocStoreSubscriber::receive(const Event& event) { //Pass a menu event to the specified handler function - if (auto selectEvent = dynamic_cast(&event); selectEvent != nullptr) - return handle(*selectEvent); + if (auto docEvent = dynamic_cast(&event); docEvent != nullptr) + return handle(*docEvent); return false; } //DocStoreSubscriber::receive diff --git a/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.cpp new file mode 100644 index 0000000..2ff67e8 --- /dev/null +++ b/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.cpp @@ -0,0 +1,76 @@ +#include "Speckle/Event/Subscriber/ProjectSubscriber.h" + +#include "Speckle/Environment/Addon.h" +#include "Speckle/Database/Identity/Link.h" +#include "Speckle/Event/Type/ProjectEvent.h" + +#ifdef ARCHICAD +#include +#endif + +using namespace active::environment; +using namespace active::event; +using namespace speckle::database; +using namespace speckle::environment; +using namespace speckle::event; + +namespace { + +#ifdef ARCHICAD + /*! + Callback for an Archicad project event + @param notifyEvent The event notification type + @param param Parameter applicable to certain events (see API docs) + */ + GSErrCode __ACENV_CALL projectCallback(API_NotifyEventID notifyEvent, Int32 param) { + if (addon() != nullptr) + addon()->publishExternal(ProjectEvent{notifyEvent, param}); + return NoError; + } +#endif + +} + + //True if a doc merge subscriber has already started (only one is required - there are no variants) +bool speckle::event::ProjectSubscriber::m_isStarted = false; + +/*-------------------------------------------------------------------- + Get the event subscription list + + return: The subscription list (an empty list will put the subscriber into a suspended state) + --------------------------------------------------------------------*/ +Subscriber::Subscription ProjectSubscriber::subscription() const { + return { {ProjectEvent::ID} }; +} //ProjectSubscriber::subscription + + +/*-------------------------------------------------------------------- + Receive a subscribed event + + event: The incoming event + + return: True if the event should be closed + --------------------------------------------------------------------*/ +bool ProjectSubscriber::receive(const Event& event) { + //Pass a menu event to the specified handler function + if (auto projectEvent = dynamic_cast(&event); projectEvent != nullptr) + return handle(*projectEvent); + return false; +} //ProjectSubscriber::receive + + +/*-------------------------------------------------------------------- + Start the participant operation + + return: True if the participant is able to continue + --------------------------------------------------------------------*/ +bool ProjectSubscriber::start() { + if (m_isStarted) + return true; + m_isStarted = true; +#ifdef ARCHICAD + return (ACAPI_ProjectOperation_CatchProjectEvent(API_AllNotificationMask, projectCallback) == NoError); +#else + return false; +#endif +} //ProjectSubscriber::start diff --git a/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h new file mode 100644 index 0000000..753affa --- /dev/null +++ b/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h @@ -0,0 +1,69 @@ +#ifndef SPECKLE_EVENT_PROJECT_SUBSCRIBER +#define SPECKLE_EVENT_PROJECT_SUBSCRIBER + +#include "Active/Event/Subscriber.h" + +namespace speckle::event { + + class ProjectEvent; + + /*! + Base class for subscribers responding to project events (open, close, quit etc) + */ + class ProjectSubscriber : public active::event::Subscriber { + public: + + // MARK: - Constructors + + /*! + Default constructor + */ + ProjectSubscriber() = default; + /*! + Copy constructor + @param source The object to copy + */ + ProjectSubscriber(const ProjectSubscriber& source) = default; + /*! + Destructor + */ + virtual ~ProjectSubscriber() {} + + // MARK: - Functions (const) + + /*! + Get the event subscription list + @return The subscription list (an empty list will put the subscriber into a suspended state) + */ + Subscription subscription() const override; + + // MARK: - Functions (mutating) + + /*! + Receive a subscribed event + @param event The incoming event + @return True if the event should be closed + */ + bool receive(const active::event::Event& event) override; + + protected: + /*! + Start the participant operation + @return True if the participant is able to continue + */ + bool start() override; + /*! + Handle a project event + @param event The project event + @return True if the event should be closed + */ + virtual bool handle(const ProjectEvent& event) = 0; + + private: + ///True if a doc merge subscriber has already started (only one is required - there are no variants) + static bool m_isStarted; + }; + +} + +#endif //SPECKLE_EVENT_PROJECT_SUBSCRIBER diff --git a/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h b/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h index e944c5a..fa8e89c 100644 --- a/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h +++ b/SpeckleLib/Speckle/Event/Type/DocStoreMergeEvent.h @@ -5,12 +5,11 @@ #include "Active/Utility/Guid.h" #include "Active/Utility/String.h" -#include "Speckle/Database/Identity/Link.h" namespace speckle::event { /*! - Class representing a selection change event + Class representing a document merge event, e.g. merging an external document */ class DocStoreMergeEvent : public active::event::Event { public: diff --git a/SpeckleLib/Speckle/Event/Type/ProjectEvent.h b/SpeckleLib/Speckle/Event/Type/ProjectEvent.h new file mode 100644 index 0000000..30c46df --- /dev/null +++ b/SpeckleLib/Speckle/Event/Type/ProjectEvent.h @@ -0,0 +1,58 @@ +#ifndef SPECKLE_EVENT_PROJECT_EVENT +#define SPECKLE_EVENT_PROJECT_EVENT + +#include "Active/Event/Event.h" + +#include "Active/Utility/Guid.h" +#include "Active/Utility/String.h" + +namespace speckle::event { + + /*! + Class representing a selection change event + */ + class ProjectEvent : public active::event::Event { + public: + + static const inline active::utility::NameID ID{active::utility::String{"project event"}, + active::utility::Guid{active::utility::String{"0ffb9ec5-2164-4fc2-aa57-17b5a1f15355"}}}; + + // MARK: - Constructors + + /*! + Default constructor + */ + ProjectEvent() : Event{ID} {} +#ifdef ARCHICAD + /*! + Constructor + @param notifyEvent The project event type + @param param An additional parameter relevant to some project events + */ + ProjectEvent(API_NotifyEventID notifyEvent, int32_t param) : Event{ID} { + m_eventID = notifyEvent; + m_param = param; + } + + /*! + Get the event type + @return The event type + */ + API_NotifyEventID getType() const { return m_eventID; } + /*! + Get the event parameter + @return The event parameter + */ + int32_t getParam() const { return m_param; } +#endif + +#ifdef ARCHICAD + //Incoming document objects to merge + API_NotifyEventID m_eventID; + int32_t m_param; +#endif + }; + +} + +#endif //SPECKLE_EVENT_PROJECT_EVENT diff --git a/SpeckleLib/Speckle/Record/Credentials/Account.cpp b/SpeckleLib/Speckle/Record/Credentials/Account.cpp index adfe089..4376f2d 100644 --- a/SpeckleLib/Speckle/Record/Credentials/Account.cpp +++ b/SpeckleLib/Speckle/Record/Credentials/Account.cpp @@ -99,6 +99,7 @@ Cargo::Unique Account::getCargo(const Inventory::Item& item) const { Set to the default package content --------------------------------------------------------------------*/ void Account::setDefault() { + base::setDefault(); m_token.clear(); m_refreshToken.clear(); m_isDefault = false; diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj index 0846643..b25bb9a 100644 --- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj +++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 210CC8A02C81E34400610F58 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 210CC89E2C81E34400610F58 /* Platform.h */; }; 212A88132AE48821001EAFE7 /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21379E082AE47A6400A1584C /* libArchicad27.a */; platformFilters = (macos, ); }; 2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351782C624FC100E5A69C /* MenuSubscriber.cpp */; }; - 2193518C2C62655700E5A69C /* MenuEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 219351892C62655700E5A69C /* MenuEvent.h */; }; 2193519B2C6278D900E5A69C /* SelectionSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351992C6278D900E5A69C /* SelectionSubscriber.cpp */; }; 219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351AC2C62CC1A00E5A69C /* Guid.cpp */; }; 219351B32C62CC1A00E5A69C /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351AE2C62CC1A00E5A69C /* String.cpp */; }; @@ -41,7 +40,8 @@ 21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */; }; 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */; }; 21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */; }; - 21D0BDBF2C90F36B0077E104 /* DocStoreMergeEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */; }; + 21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */; }; + 21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */; }; 21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F382C6B880B008B6A06 /* JSBaseTransport.cpp */; }; 21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */; }; 21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F602C6D0286008B6A06 /* GetBindingsMethodNames.cpp */; }; @@ -143,6 +143,9 @@ 21D0BDBA2C90F2830077E104 /* DocStoreSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocStoreSubscriber.h; sourceTree = ""; }; 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocStoreSubscriber.cpp; sourceTree = ""; }; 21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocStoreMergeEvent.h; sourceTree = ""; }; + 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectSubscriber.cpp; sourceTree = ""; }; + 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectSubscriber.h; sourceTree = ""; }; + 21D0BDC62C9245E40077E104 /* ProjectEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectEvent.h; sourceTree = ""; }; 21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = ""; }; 21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = ""; }; 21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = ""; }; @@ -263,6 +266,8 @@ 21D0BDBA2C90F2830077E104 /* DocStoreSubscriber.h */, 219351782C624FC100E5A69C /* MenuSubscriber.cpp */, 219351792C624FC100E5A69C /* MenuSubscriber.h */, + 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */, + 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */, 219351992C6278D900E5A69C /* SelectionSubscriber.cpp */, 219351982C6278D900E5A69C /* SelectionSubscriber.h */, ); @@ -274,6 +279,7 @@ children = ( 21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */, 219351892C62655700E5A69C /* MenuEvent.h */, + 21D0BDC62C9245E40077E104 /* ProjectEvent.h */, 2193519C2C627E3100E5A69C /* SelectionEvent.h */, ); path = Type; @@ -470,7 +476,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 21D0BDBF2C90F36B0077E104 /* DocStoreMergeEvent.h in Headers */, 21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */, 210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */, 210CC8A02C81E34400610F58 /* Platform.h in Headers */, @@ -485,7 +490,7 @@ 210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */, 21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */, 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */, - 2193518C2C62655700E5A69C /* MenuEvent.h in Headers */, + 21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */, 21D0BD312C86FE090077E104 /* Index.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -627,6 +632,7 @@ 21D0BD2B2C86FC350077E104 /* Record.cpp in Sources */, 21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */, 210CC8902C81A98500610F58 /* Guid64.cpp in Sources */, + 21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */, 21D0BD322C86FE090077E104 /* Link.cpp in Sources */, 219351B32C62CC1A00E5A69C /* String.cpp in Sources */, 219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */, From 8b765ec3d7ee6779a60dab51ce64aceaddd9fc2d Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Wed, 11 Sep 2024 23:18:03 +0100 Subject: [PATCH 05/16] Added ModelCardDatabase::getSubscription --- .../Database/Model/Card/ModelCardDatabase.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp index 264af71..4117cea 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp @@ -44,7 +44,7 @@ namespace { --------------------------------------------------------------------*/ ModelCardDatabase::ModelCardDatabase() { - auto engine = std::make_shared(modelCardDBaseName, + auto engine = std::make_unique(modelCardDBaseName, //Schema DBaseSchema{active::utility::String{modelCardDBaseName}, //Tables @@ -56,7 +56,7 @@ ModelCardDatabase::ModelCardDatabase() { } } ); - m_store = std::make_unique(std::move(engine)); + m_store = std::make_shared(std::move(engine)); } //ModelCardDatabase::ModelCardDatabase @@ -84,3 +84,13 @@ Vector ModelCardDatabase::getCards() const { std::unique_ptr ModelCardDatabase::wrapper() const { return m_store->wrapper(); } //ModelCardDatabase::wrapper + + +/*-------------------------------------------------------------------- + Get the database subscription (the content is document-based, and must react to document operations) + + return: The database subscription (add weakly to publisher) + --------------------------------------------------------------------*/ +std::shared_ptr ModelCardDatabase::getSubscription() const { + return dynamic_pointer_cast(m_store); +} //ModelCardDatabase::getSubscription From 461047f04af1ec773f5e6f0de672a875f5d9dc77 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Thu, 12 Sep 2024 00:10:03 +0100 Subject: [PATCH 06/16] Updated VS projects Updated gitignore for temp resource files --- .gitignore | 4 ++- SpeckleConnector/Connector.vcxproj | 4 +++ SpeckleConnector/Connector.vcxproj.filters | 12 +++++++ .../Database/Model/Card/CardSetting.h | 2 +- SpeckleLib/SpeckleLib17.vcxproj | 9 +++++ SpeckleLib/SpeckleLib17.vcxproj.filters | 33 +++++++++++++++++++ 6 files changed, 62 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4677eaf..3230d7c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,6 @@ CMakeFiles/ XCBuildData/ **/*.xcsettings *.log -.idea \ No newline at end of file +.idea +*.mui +*.aps \ No newline at end of file diff --git a/SpeckleConnector/Connector.vcxproj b/SpeckleConnector/Connector.vcxproj index 355ea9f..5c34307 100644 --- a/SpeckleConnector/Connector.vcxproj +++ b/SpeckleConnector/Connector.vcxproj @@ -93,6 +93,8 @@ + + @@ -124,6 +126,8 @@ + + diff --git a/SpeckleConnector/Connector.vcxproj.filters b/SpeckleConnector/Connector.vcxproj.filters index 2303713..d63175d 100644 --- a/SpeckleConnector/Connector.vcxproj.filters +++ b/SpeckleConnector/Connector.vcxproj.filters @@ -162,6 +162,12 @@ Connector\Interface\Browser\Bridge\Send\Arg + + Connector\Database\Model\Card + + + Connector\Database\Model\Card + @@ -255,5 +261,11 @@ Connector\Interface\Browser\Bridge\Send\Arg + + Connector\Database\Model\Card + + + Connector\Database\Model\Card + \ No newline at end of file diff --git a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h b/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h index 752dc51..37ca2da 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h +++ b/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h @@ -91,7 +91,7 @@ namespace connector::database { private: ///A unique ID for the setting - speckle::utility::String m_ID = {speckle::utility::Guid{true}}; + speckle::utility::String m_ID = {active::utility::Guid{true}.operator active::utility::String()}; ///The model ID speckle::utility::String m_title; ///The project ID diff --git a/SpeckleLib/SpeckleLib17.vcxproj b/SpeckleLib/SpeckleLib17.vcxproj index 8a2bf4a..e79772c 100644 --- a/SpeckleLib/SpeckleLib17.vcxproj +++ b/SpeckleLib/SpeckleLib17.vcxproj @@ -23,11 +23,17 @@ + + + + + + @@ -61,9 +67,12 @@ + + + diff --git a/SpeckleLib/SpeckleLib17.vcxproj.filters b/SpeckleLib/SpeckleLib17.vcxproj.filters index 90c6412..078a9b6 100644 --- a/SpeckleLib/SpeckleLib17.vcxproj.filters +++ b/SpeckleLib/SpeckleLib17.vcxproj.filters @@ -56,6 +56,12 @@ {ef1710f6-d890-4286-8fb2-f5c432a2c5ac} + + {afbc554e-df7d-4310-a967-4df8e9febcd0} + + + {c4146af8-d1a1-44cc-9810-cc8da1a705a8} + @@ -169,6 +175,24 @@ Speckle\Environment + + Speckle\Event\Subscriber + + + Speckle\Event\Subscriber + + + Speckle\Event\Type + + + Speckle\Event\Type + + + Speckle\Database\Storage\DocumentStore + + + Speckle\Database\Storage\DocumentStore + @@ -237,6 +261,15 @@ Speckle\Environment + + Speckle\Event\Subscriber + + + Speckle\Event\Subscriber + + + Speckle\Database\Storage\DocumentStore + From 5dcab380862beb5640965693c9892ad9557e4ca6 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Thu, 12 Sep 2024 18:00:22 +0100 Subject: [PATCH 07/16] Added "base.AddModel" method Storage write methods Subscriber implementations should be 'virtual Subscriber' to allow multiple inheritance --- .../Connector.xcodeproj/project.pbxproj | 6 ++ .../Database/Model/Card/ModelCardDatabase.cpp | 24 +++-- .../Database/Model/Card/ModelCardDatabase.h | 14 ++- .../Browser/Bridge/Base/AddModel.cpp | 36 +++++++ .../Interface/Browser/Bridge/Base/AddModel.h | 40 ++++++++ .../Speckle/Database/AccountDatabase.cpp | 2 +- .../DocumentStore/DocumentStoreCore.cpp | 46 +++++++++ .../Storage/DocumentStore/DocumentStoreCore.h | 24 +++++ .../DocumentStore/DocumentStoreEngine.h | 97 +++++++++++++------ .../Event/Subscriber/DocStoreSubscriber.h | 2 +- .../Speckle/Event/Subscriber/MenuSubscriber.h | 2 +- .../Event/Subscriber/ProjectSubscriber.h | 2 +- .../Event/Subscriber/SelectionSubscriber.h | 2 +- 13 files changed, 252 insertions(+), 45 deletions(-) create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index 66e1975..ed5b4b7 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD982C8F154B0077E104 /* SendFilter.cpp */; }; 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */; }; 21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */; }; + 21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */; }; 21D1E9AD2BF14AF200957EAA /* BIMData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9152BF14AEC00957EAA /* BIMData.framework */; }; 21D1E9AE2BF14AF200957EAA /* TeamworkPortalServerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */; }; 21D1E9AF2BF14AF200957EAA /* GDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9172BF14AEC00957EAA /* GDL.framework */; }; @@ -327,6 +328,8 @@ 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModelCard.cpp; sourceTree = ""; }; 21D0BDA92C8F363E0077E104 /* CardSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardSetting.h; sourceTree = ""; }; 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CardSetting.cpp; sourceTree = ""; }; + 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddModel.cpp; sourceTree = ""; }; + 21D0BDCE2C92DAC60077E104 /* AddModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddModel.h; sourceTree = ""; }; 21D1E9152BF14AEC00957EAA /* BIMData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BIMData.framework; path = "../Archicad 27/Support/Frameworks/BIMData.framework"; sourceTree = ""; }; 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TeamworkPortalServerClient.framework; path = "../Archicad 27/Support/Frameworks/TeamworkPortalServerClient.framework"; sourceTree = ""; }; 21D1E9172BF14AEC00957EAA /* GDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GDL.framework; path = "../Archicad 27/Support/Frameworks/GDL.framework"; sourceTree = ""; }; @@ -904,6 +907,8 @@ 21B67CAB2C77329800FD64FC /* Base */ = { isa = PBXGroup; children = ( + 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */, + 21D0BDCE2C92DAC60077E104 /* AddModel.h */, 21B67CEA2C78D27200FD64FC /* Arg */, 21B67CA52C77329800FD64FC /* BaseBridge.cpp */, 21B67CA62C77329800FD64FC /* BaseBridge.h */, @@ -1340,6 +1345,7 @@ 21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */, 21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */, 21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */, + 21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */, 21B67CF72C78D4DE00FD64FC /* GetComplexType.cpp in Sources */, 21B67CAE2C77329800FD64FC /* GetSourceApplicationVersion.cpp in Sources */, 21B67CC32C77649F00FD64FC /* GetDocumentState.cpp in Sources */, diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp index 4117cea..c0c1e84 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp @@ -18,7 +18,10 @@ using namespace speckle::utility; namespace connector::database { ///ModelCard database engine declaration - using ModelCardEngine = DocumentStoreEngine; + class ModelCardDatabase::Engine : public DocumentStoreEngine { + using base = DocumentStoreEngine; + using base::base; + }; ///ModelCard database storage declaration class ModelCardDatabase::Store : public active::database::Storage(modelCardDBaseName, + auto engine = std::make_shared(modelCardDBaseName, //Schema DBaseSchema{active::utility::String{modelCardDBaseName}, //Tables @@ -56,7 +58,7 @@ ModelCardDatabase::ModelCardDatabase() { } } ); - m_store = std::make_shared(std::move(engine)); + m_store = std::make_shared(m_engine); } //ModelCardDatabase::ModelCardDatabase @@ -76,6 +78,16 @@ Vector ModelCardDatabase::getCards() const { } //ModelCardDatabase::getCards +/*-------------------------------------------------------------------- + Write a card to storage + + card: The card to write + --------------------------------------------------------------------*/ +void ModelCardDatabase::write(const ModelCard& card) const { + m_store->write(card); +} //ModelCardDatabase::write + + /*-------------------------------------------------------------------- Get a serialisation wrapper for the database @@ -91,6 +103,6 @@ std::unique_ptr ModelCardDatabase::wrapper() const { return: The database subscription (add weakly to publisher) --------------------------------------------------------------------*/ -std::shared_ptr ModelCardDatabase::getSubscription() const { - return dynamic_pointer_cast(m_store); +std::shared_ptr ModelCardDatabase::getSubscription() { + return std::dynamic_pointer_cast(m_engine); } //ModelCardDatabase::getSubscription diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h index 4d452be..a732da2 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h @@ -34,22 +34,30 @@ namespace connector::database { @return All the cards */ active::container::Vector getCards() const; + /*! + Write a card to storage + @param card The card to write + */ + void write(const ModelCard& card) const; /*! Get a serialisation wrapper for the database @return A database wrapper */ std::unique_ptr wrapper() const; + + // MARK: - Functions (mutating) + /*! Get the database subscription (the content is document-based, and must react to document operations) @return The database subscription (add weakly to publisher) */ - std::shared_ptr getSubscription() const; + std::shared_ptr getSubscription(); - // MARK: - Functions (mutating) - private: + class Engine; class Store; ///Model card database storage + std::shared_ptr m_engine; std::shared_ptr m_store; }; diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp new file mode 100644 index 0000000..c7eb19c --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp @@ -0,0 +1,36 @@ +#include "Connector/Interface/Browser/Bridge/Base/AddModel.h" + +#include "Active/Serialise/CargoHold.h" +#include "Connector/Connector.h" +#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" + +using namespace active::container; +using namespace active::serialise; +using namespace connector::database; +using namespace connector::interfac::browser::bridge; +using namespace speckle::utility; + +namespace { + + using WrappedValue = active::serialise::CargoHold; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +AddModel::AddModel() : BridgeMethod{"AddModel", [&](ModelCardEventWrapper card) { + return run(card.get()); +}} {} + + +/*-------------------------------------------------------------------- + Add a model card to document storage + + card: The card to add + --------------------------------------------------------------------*/ +void AddModel::run(ModelCard& card) const { + if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) + modelCardDBase->write(card); +} //AddModel::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h new file mode 100644 index 0000000..1816944 --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h @@ -0,0 +1,40 @@ +#ifndef CONNECTOR_INTERFACE_BRIDGE_ADD_MODEL +#define CONNECTOR_INTERFACE_BRIDGE_ADD_MODEL + +#include "Active/Serialise/CargoHold.h" +#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Connector/Database/Model/Card/ModelCard.h" +#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" + +namespace connector::interfac::browser::bridge { + + ///Argument parameter for a string + using CardHold = active::serialise::CargoHold; + ///Argument type for this method + using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType; + + /*! + JS Function class to add a model card to the document storage + */ + class AddModel : public speckle::interfac::browser::bridge::BridgeMethod { + public: + + // MARK: - Constructors + + /*! + Default constructor + */ + AddModel(); + + // MARK: - Functions (const) + + /*! + Add a model card to document storage + @param card The card to add + */ + void run(connector::database::ModelCard& card) const; + }; + +} + +#endif //CONNECTOR_INTERFACE_BRIDGE_ADD_MODEL diff --git a/SpeckleLib/Speckle/Database/AccountDatabase.cpp b/SpeckleLib/Speckle/Database/AccountDatabase.cpp index c6847c1..b6f2967 100644 --- a/SpeckleLib/Speckle/Database/AccountDatabase.cpp +++ b/SpeckleLib/Speckle/Database/AccountDatabase.cpp @@ -56,7 +56,7 @@ AccountDatabase::AccountDatabase(const active::file::Path& path) { //Create accounts database storage (with schema) m_store = std::make_unique( //Engine - std::make_unique(path, + std::make_shared(path, //Schema DBaseSchema{active::utility::String{accountsDBaseName}, //Tables diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp index 6456818..b0a6b77 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -13,6 +13,7 @@ #include #endif +using namespace active::event; using namespace active::setting; using namespace speckle::database; using namespace speckle::environment; @@ -233,3 +234,48 @@ void DocumentStoreCore::writeStore() { } #endif } //DocumentStoreCore::writeStore + + +/*-------------------------------------------------------------------- + Get the event subscription list + + return: The subscription list (an empty list will put the subscriber into a suspended state) + --------------------------------------------------------------------*/ +Subscriber::Subscription DocumentStoreCore::subscription() const { + auto result = DocStoreSubscriber::subscription(); + auto other = ProjectSubscriber::subscription(); + result.insert(other.begin(), other.end()); + return result; +} //DocumentStoreCore::subscription + + +/*-------------------------------------------------------------------- + Receive a subscribed event + + event: The incoming event + + return: True if the event should be closed + --------------------------------------------------------------------*/ +bool DocumentStoreCore::receive(const active::event::Event& event) { + return DocStoreSubscriber::receive(event) || ProjectSubscriber::receive(event); +} //DocumentStoreCore::receive + + +/*-------------------------------------------------------------------- + Attach participant components to the app (as required) + + return: True if the participant is able to function + --------------------------------------------------------------------*/ +bool DocumentStoreCore::attach() { + return DocStoreSubscriber::attach() && ProjectSubscriber::attach(); +} //DocumentStoreCore::attach + + +/*-------------------------------------------------------------------- + Start the participant operation + + return: True if the participant is able to continue + --------------------------------------------------------------------*/ +bool DocumentStoreCore::start() { + return DocStoreSubscriber::start() && ProjectSubscriber::start(); +} //DocumentStoreCore::start diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h index 450d207..77b98e0 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h @@ -105,6 +105,30 @@ namespace speckle::database { Reset the stored data (some external change has invalidated previous data, e.g. the document was closed) */ virtual void resetStore() = 0; + + // MARK: Subscriber functions + + /*! + Get the event subscription list + @return The subscription list (an empty list will put the subscriber into a suspended state) + */ + Subscription subscription() const override; + /*! + Receive a subscribed event + @param event The incoming event + @return True if the event should be closed + */ + bool receive(const active::event::Event& event) override; + /*! + Attach participant components to the app (as required) + @return True if the participant is able to function + */ + bool attach() override; + /*! + Start the participant operation + @return True if the participant is able to continue + */ + bool start() override; private: ///The database schema diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index 6f7de19..978b1c7 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -30,10 +30,11 @@ namespace speckle::database { Due to the fact that these records are intended to represent a single table and are stored in a document, the concepts of 'table' and 'document' aren't currently applicable (this could be extended in future if there is a use-case) @tparam Obj Interface for the stored object. NB: This can be a base class for an object hierarchy, not necessarily a concrete class + @tparam ObjWrapper Wrapper type for (de)serialising objects @tparam Transport The serialisation transport mechanism for objects @tparam ObjID The object identifier type, e.g. Guid */ - template + template requires DocumentStorable class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { public: @@ -80,6 +81,16 @@ namespace speckle::database { */ active::container::Vector getObjects(const Filter& filter, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; + /*! + Write an object to the database + @param object The object to write + @param objID The object ID + @param objDocID The object document-specific ID (unique within a specific document - nullopt if not document-bound) + @param tableID Optional table ID (defaults to the first table) + @param documentID Optional document ID (when the object is bound to a specific document) + */ + void write(const Obj& object, const ObjID& objID, std::optional objDocID = std::nullopt, + utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; /*! Erase an object by index @param ID The object ID @@ -87,7 +98,8 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) @throw Exception thrown on SQL error */ - void erase(const ObjID& ID, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; + void erase(const ObjID& ID, std::optional tableID = std::nullopt, + std::optional documentID = std::nullopt) const override; /*! Erase all objects @param tableID Optional table ID (defaults to the first table) @@ -133,9 +145,9 @@ namespace speckle::database { return: The cached records (nullptr on failure) --------------------------------------------------------------------*/ - template + template requires DocumentStorable - typename DocumentStoreEngine::Cache* DocumentStoreEngine::getCache() const { + typename DocumentStoreEngine::Cache* DocumentStoreEngine::getCache() const { if (m_cache) return m_cache.get(); //Read the data stored in the document @@ -144,9 +156,12 @@ namespace speckle::database { if (!storedData) return m_cache.get(); //Return an empty container if there's no data //Import the document data into the record cache - Transport().receive(std::forward(*m_cache), active::serialise::Identity{}, storedData); + if constexpr (std::is_same_v) + Transport().receive(std::forward(*m_cache), active::serialise::Identity{}, storedData); + else + Transport().receive(ObjWrapper{*m_cache}, active::serialise::Identity{}, storedData); return m_cache.get(); - } //DocumentStoreEngine::getCache + } //DocumentStoreEngine::getCache /*-------------------------------------------------------------------- @@ -158,12 +173,12 @@ namespace speckle::database { return: The requested object (nullptr on failure) --------------------------------------------------------------------*/ - template + template requires DocumentStorable - std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, std::optional tableID, + std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, std::optional tableID, std::optional documentID) const { return getCache()->read(ID); - } //DocumentStoreEngine::getObject + } //DocumentStoreEngine::getObject /*-------------------------------------------------------------------- @@ -174,12 +189,12 @@ namespace speckle::database { return: The requested objects (nullptr on failure) --------------------------------------------------------------------*/ - template + template requires DocumentStorable - active::container::Vector DocumentStoreEngine::getObjects(std::optional tableID, + active::container::Vector DocumentStoreEngine::getObjects(std::optional tableID, std::optional documentID) const { return getCache()->read(); - } //DocumentStoreEngine::getObjects + } //DocumentStoreEngine::getObjects /*-------------------------------------------------------------------- @@ -191,12 +206,29 @@ namespace speckle::database { return: The requested objects (nullptr on failure) --------------------------------------------------------------------*/ - template + template requires DocumentStorable - active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, std::optional tableID, + active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, std::optional tableID, std::optional documentID) const { return getCache()->read(filter); - } //DocumentStoreEngine::getObjects + } //DocumentStoreEngine::getObjects + + + /*-------------------------------------------------------------------- + Write an object to the database + + object: The object to write + objID: The object ID + objDocID: The object document-specific ID (unique within a specific document - nullopt if not document-bound) + tableID: Optional table ID (defaults to the first table) + documentID: Optional document ID (when the object is bound to a specific document) + --------------------------------------------------------------------*/ + template + requires DocumentStorable + void DocumentStoreEngine::write(const Obj& object, const ObjID& objID, std::optional objDocID, + utility::String::Option tableID, utility::String::Option documentID) const { + getCache()->write(object); //NB: In future we might support duplicating records if objID != obj.id + } //DocumentStoreEngine::write /*-------------------------------------------------------------------- @@ -208,12 +240,12 @@ namespace speckle::database { return: True if the object was successfully erased --------------------------------------------------------------------*/ - template + template requires DocumentStorable - void DocumentStoreEngine::erase(const ObjID& ID, std::optional tableID, + void DocumentStoreEngine::erase(const ObjID& ID, std::optional tableID, std::optional documentID) const { getCache()->erase(ID); - } //DocumentStoreEngine::erase + } //DocumentStoreEngine::erase /*-------------------------------------------------------------------- @@ -222,11 +254,11 @@ namespace speckle::database { tableID: Optional table ID (defaults to the first table) documentID: Optional document ID (filter for this document only - nullopt = all objects) --------------------------------------------------------------------*/ - template + template requires DocumentStorable - void DocumentStoreEngine::erase(std::optional tableID, std::optional documentID) const { + void DocumentStoreEngine::erase(std::optional tableID, std::optional documentID) const { getCache()->erase(); - } //DocumentStoreEngine::erase + } //DocumentStoreEngine::erase /*-------------------------------------------------------------------- @@ -234,16 +266,16 @@ namespace speckle::database { return: The database outline --------------------------------------------------------------------*/ - template + template requires DocumentStorable - DocumentStoreEngine::Outline DocumentStoreEngine::getOutline() const { + DocumentStoreEngine::Outline DocumentStoreEngine::getOutline() const { Outline result; if (getSchema().empty()) return result; //NB: Currently implementing only a single table in a document store result.emplace_back(std::make_pair(getSchema()[0].ID, getCache()->keys())); return result; - } //DocumentStoreEngine::getOutline + } //DocumentStoreEngine::getOutline /*-------------------------------------------------------------------- @@ -251,13 +283,13 @@ namespace speckle::database { return: Data to store from the latest records --------------------------------------------------------------------*/ - template + template requires DocumentStorable - active::utility::Memory DocumentStoreEngine::buildStore() { + active::utility::Memory DocumentStoreEngine::buildStore() { active::utility::Memory result; Transport().send(std::forward(*getCache()), active::serialise::Identity{}, result); return result; - } //DocumentStoreEngine::buildStore + } //DocumentStoreEngine::buildStore /*-------------------------------------------------------------------- @@ -267,15 +299,18 @@ namespace speckle::database { return: The merged data to be stored --------------------------------------------------------------------*/ - template + template requires DocumentStorable - void DocumentStoreEngine::mergeStore(const active::utility::Memory& toMerge) { + void DocumentStoreEngine::mergeStore(const active::utility::Memory& toMerge) { //Import the incoming records from the data to merge Cache incoming; - Transport().receive(std::forward(incoming), active::serialise::Identity{}, toMerge); + if constexpr (std::is_same_v) + Transport().receive(std::forward(incoming), active::serialise::Identity{}, toMerge); + else + Transport().receive(ObjWrapper{incoming}, active::serialise::Identity{}, toMerge); //Get the data currently stored in the document getCache()->merge(std::forward(incoming)); - } //DocumentStoreEngine::mergeStore + } //DocumentStoreEngine::mergeStore } diff --git a/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h index d14e84c..1f90c94 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h +++ b/SpeckleLib/Speckle/Event/Subscriber/DocStoreSubscriber.h @@ -10,7 +10,7 @@ namespace speckle::event { /*! Base class for subscribers responding to document merge operations (notably those managing custom data in the document) */ - class DocStoreSubscriber : public active::event::Subscriber { + class DocStoreSubscriber : public virtual active::event::Subscriber { public: // MARK: - Constructors diff --git a/SpeckleLib/Speckle/Event/Subscriber/MenuSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/MenuSubscriber.h index d36a279..86237ee 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/MenuSubscriber.h +++ b/SpeckleLib/Speckle/Event/Subscriber/MenuSubscriber.h @@ -25,7 +25,7 @@ namespace speckle::event { /*! Base class for subscribers handling a UI menu (from the app menu bar) */ - class MenuSubscriber : public active::event::Subscriber { + class MenuSubscriber : public virtual active::event::Subscriber { public: // MARK: - Constructors diff --git a/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h index 753affa..60096ca 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h +++ b/SpeckleLib/Speckle/Event/Subscriber/ProjectSubscriber.h @@ -10,7 +10,7 @@ namespace speckle::event { /*! Base class for subscribers responding to project events (open, close, quit etc) */ - class ProjectSubscriber : public active::event::Subscriber { + class ProjectSubscriber : public virtual active::event::Subscriber { public: // MARK: - Constructors diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h index 56314dd..975eb0c 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h +++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h @@ -10,7 +10,7 @@ namespace speckle::event { /*! Base class for subscribers responding to selection changes */ - class SelectionSubscriber : public active::event::Subscriber { + class SelectionSubscriber : public virtual active::event::Subscriber { public: // MARK: - Constructors From 850cd36d73ad646dbe0bfee8c3ebafc2119487c3 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Thu, 12 Sep 2024 18:48:57 +0100 Subject: [PATCH 08/16] Added UpdateModel and RemoveModel Linked new methods to baseBinding --- .../Connector.xcodeproj/project.pbxproj | 12 ++++++ .../Database/Model/Card/ModelCardDatabase.cpp | 10 +++++ .../Database/Model/Card/ModelCardDatabase.h | 5 +++ .../Browser/Bridge/Base/AddModel.cpp | 1 - .../Browser/Bridge/Base/BaseBridge.cpp | 6 +++ .../Browser/Bridge/Base/RemoveModel.cpp | 35 ++++++++++++++++ .../Browser/Bridge/Base/RemoveModel.h | 40 +++++++++++++++++++ .../Browser/Bridge/Base/UpdateModel.cpp | 35 ++++++++++++++++ .../Browser/Bridge/Base/UpdateModel.h | 40 +++++++++++++++++++ 9 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index ed5b4b7..d96ff81 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -51,6 +51,8 @@ 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */; }; 21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */; }; 21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */; }; + 21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */; }; + 21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */; }; 21D1E9AD2BF14AF200957EAA /* BIMData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9152BF14AEC00957EAA /* BIMData.framework */; }; 21D1E9AE2BF14AF200957EAA /* TeamworkPortalServerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */; }; 21D1E9AF2BF14AF200957EAA /* GDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9172BF14AEC00957EAA /* GDL.framework */; }; @@ -330,6 +332,10 @@ 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CardSetting.cpp; sourceTree = ""; }; 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddModel.cpp; sourceTree = ""; }; 21D0BDCE2C92DAC60077E104 /* AddModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddModel.h; sourceTree = ""; }; + 21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UpdateModel.cpp; sourceTree = ""; }; + 21D0BDD32C935D1A0077E104 /* UpdateModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateModel.h; sourceTree = ""; }; + 21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveModel.cpp; sourceTree = ""; }; + 21D0BDD62C935DAE0077E104 /* RemoveModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveModel.h; sourceTree = ""; }; 21D1E9152BF14AEC00957EAA /* BIMData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BIMData.framework; path = "../Archicad 27/Support/Frameworks/BIMData.framework"; sourceTree = ""; }; 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TeamworkPortalServerClient.framework; path = "../Archicad 27/Support/Frameworks/TeamworkPortalServerClient.framework"; sourceTree = ""; }; 21D1E9172BF14AEC00957EAA /* GDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GDL.framework; path = "../Archicad 27/Support/Frameworks/GDL.framework"; sourceTree = ""; }; @@ -922,6 +928,10 @@ 21B67CA82C77329800FD64FC /* GetSourceApplicationName.h */, 21B67CA92C77329800FD64FC /* GetSourceApplicationVersion.cpp */, 21B67CAA2C77329800FD64FC /* GetSourceApplicationVersion.h */, + 21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */, + 21D0BDD62C935DAE0077E104 /* RemoveModel.h */, + 21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */, + 21D0BDD32C935D1A0077E104 /* UpdateModel.h */, ); path = Base; sourceTree = ""; @@ -1359,9 +1369,11 @@ 21B67CD92C78C83800FD64FC /* TestBridge.cpp in Sources */, 214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */, 21B67CC02C775A0D00FD64FC /* GetDocumentInfo.cpp in Sources */, + 21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */, 21B67CE72C78D23B00FD64FC /* ConnectorConfig.cpp in Sources */, 21B67CAD2C77329800FD64FC /* GetSourceApplicationName.cpp in Sources */, 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */, + 21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */, 21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */, 21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */, 21F69F8D2C70D7EE008B6A06 /* GetAccounts.cpp in Sources */, diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp index c0c1e84..aa6175b 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp @@ -88,6 +88,16 @@ void ModelCardDatabase::write(const ModelCard& card) const { } //ModelCardDatabase::write +/*-------------------------------------------------------------------- + Erase a card + + cardID: The ID of the card to erase + --------------------------------------------------------------------*/ +void ModelCardDatabase::erase(const speckle::utility::String& cardID) const { + m_store->erase(cardID); +} //ModelCardDatabase::erase + + /*-------------------------------------------------------------------- Get a serialisation wrapper for the database diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h index a732da2..90a770b 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h +++ b/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h @@ -39,6 +39,11 @@ namespace connector::database { @param card The card to write */ void write(const ModelCard& card) const; + /*! + Erase a card + @param cardID The ID of the card to erase + */ + void erase(const speckle::utility::String& cardID) const; /*! Get a serialisation wrapper for the database @return A database wrapper diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp index c7eb19c..262be5c 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp @@ -1,6 +1,5 @@ #include "Connector/Interface/Browser/Bridge/Base/AddModel.h" -#include "Active/Serialise/CargoHold.h" #include "Connector/Connector.h" #include "Connector/Database/Model/Card/ModelCardDatabase.h" #include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp index 94c5127..f40155f 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp @@ -1,10 +1,13 @@ #include "Connector/Interface/Browser/Bridge/Base/BaseBridge.h" +#include "Connector/Interface/Browser/Bridge/Base/AddModel.h" #include "Connector/Interface/Browser/Bridge/Base/GetConnectorVersion.h" #include "Connector/Interface/Browser/Bridge/Base/GetDocumentInfo.h" #include "Connector/Interface/Browser/Bridge/Base/GetDocumentState.h" #include "Connector/Interface/Browser/Bridge/Base/GetSourceApplicationName.h" #include "Connector/Interface/Browser/Bridge/Base/GetSourceApplicationVersion.h" +#include "Connector/Interface/Browser/Bridge/Base/RemoveModel.h" +#include "Connector/Interface/Browser/Bridge/Base/UpdateModel.h" using namespace connector::interfac::browser::bridge; @@ -13,9 +16,12 @@ using namespace connector::interfac::browser::bridge; --------------------------------------------------------------------*/ BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} { //Add bridge methods + addMethod(); addMethod(); addMethod(); addMethod(); addMethod(); addMethod(); + addMethod(); + addMethod(); } //BaseBridge::BaseBridge diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp new file mode 100644 index 0000000..ca7d0e7 --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp @@ -0,0 +1,35 @@ +#include "Connector/Interface/Browser/Bridge/Base/RemoveModel.h" + +#include "Connector/Connector.h" +#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" + +using namespace active::container; +using namespace active::serialise; +using namespace connector::database; +using namespace connector::interfac::browser::bridge; +using namespace speckle::utility; + +namespace { + + using WrappedValue = active::serialise::CargoHold; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +RemoveModel::RemoveModel() : BridgeMethod{"RemoveModel", [&](ModelCardEventWrapper card) { + return run(card.get()); +}} {} + + +/*-------------------------------------------------------------------- + Add a model card to document storage + + card: The card to add + --------------------------------------------------------------------*/ +void RemoveModel::run(ModelCard& card) const { + if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) + modelCardDBase->erase(card.getID()); +} //RemoveModel::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h new file mode 100644 index 0000000..00c8aab --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h @@ -0,0 +1,40 @@ +#ifndef CONNECTOR_INTERFACE_BRIDGE_REMOVE_MODEL +#define CONNECTOR_INTERFACE_BRIDGE_REMOVE_MODEL + +#include "Active/Serialise/CargoHold.h" +#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Connector/Database/Model/Card/ModelCard.h" +#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" + +namespace connector::interfac::browser::bridge { + + ///Argument parameter for a string + using CardHold = active::serialise::CargoHold; + ///Argument type for this method + using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType; + + /*! + JS Function class to add a model card to the document storage + */ + class RemoveModel : public speckle::interfac::browser::bridge::BridgeMethod { + public: + + // MARK: - Constructors + + /*! + Default constructor + */ + RemoveModel(); + + // MARK: - Functions (const) + + /*! + Add a model card to document storage + @param card The card to add + */ + void run(connector::database::ModelCard& card) const; + }; + +} + +#endif //CONNECTOR_INTERFACE_BRIDGE_REMOVE_MODEL diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp new file mode 100644 index 0000000..301349a --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp @@ -0,0 +1,35 @@ +#include "Connector/Interface/Browser/Bridge/Base/UpdateModel.h" + +#include "Connector/Connector.h" +#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" + +using namespace active::container; +using namespace active::serialise; +using namespace connector::database; +using namespace connector::interfac::browser::bridge; +using namespace speckle::utility; + +namespace { + + using WrappedValue = active::serialise::CargoHold; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +UpdateModel::UpdateModel() : BridgeMethod{"UpdateModel", [&](ModelCardEventWrapper card) { + return run(card.get()); +}} {} + + +/*-------------------------------------------------------------------- + Add a model card to document storage + + card: The card to add + --------------------------------------------------------------------*/ +void UpdateModel::run(ModelCard& card) const { + if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) + modelCardDBase->write(card); +} //UpdateModel::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h new file mode 100644 index 0000000..41ea93b --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h @@ -0,0 +1,40 @@ +#ifndef CONNECTOR_INTERFACE_BRIDGE_UPDATE_MODEL +#define CONNECTOR_INTERFACE_BRIDGE_UPDATE_MODEL + +#include "Active/Serialise/CargoHold.h" +#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Connector/Database/Model/Card/ModelCard.h" +#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" + +namespace connector::interfac::browser::bridge { + + ///Argument parameter for a string + using CardHold = active::serialise::CargoHold; + ///Argument type for this method + using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType; + + /*! + JS Function class to add a model card to the document storage + */ + class UpdateModel : public speckle::interfac::browser::bridge::BridgeMethod { + public: + + // MARK: - Constructors + + /*! + Default constructor + */ + UpdateModel(); + + // MARK: - Functions (const) + + /*! + Add a model card to document storage + @param card The card to add + */ + void run(connector::database::ModelCard& card) const; + }; + +} + +#endif //CONNECTOR_INTERFACE_BRIDGE_UPDATE_MODEL From 90211900e1afa7d94aa9371bc50e6a2b2abee453 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Fri, 13 Sep 2024 11:51:40 +0100 Subject: [PATCH 09/16] Interim commit - builds with some warnings Simplication of record identifiers Starting implementation of SenderModelCar Implementation of SendFilters in progress --- .../Connector.xcodeproj/project.pbxproj | 74 ++++++----- SpeckleConnector/Connector/Connector.cpp | 2 +- .../{Model/Card => }/ModelCardDatabase.cpp | 22 ++-- .../{Model/Card => }/ModelCardDatabase.h | 6 +- .../Browser/Bridge/Base/AddModel.cpp | 4 +- .../Interface/Browser/Bridge/Base/AddModel.h | 6 +- .../Browser/Bridge/Base/GetDocumentState.cpp | 5 +- .../Browser/Bridge/Base/RemoveModel.cpp | 3 +- .../Browser/Bridge/Base/RemoveModel.h | 6 +- .../Browser/Bridge/Base/UpdateModel.cpp | 3 +- .../Browser/Bridge/Base/UpdateModel.h | 6 +- .../Browser/Bridge/Send/GetSendFilters.cpp | 3 +- .../Card => Record/Model}/CardSetting.cpp | 4 +- .../Model/Card => Record/Model}/CardSetting.h | 8 +- .../Filter/DirectSelectionSendFilter.cpp | 80 ++++++++++++ .../Model/Filter/DirectSelectionSendFilter.h | 88 +++++++++++++ .../Model/Filter}/SendFilter.cpp | 16 +-- .../Arg => Record/Model/Filter}/SendFilter.h | 51 +++++--- .../Model/Card => Record/Model}/ModelCard.cpp | 4 +- .../Model/Card => Record/Model}/ModelCard.h | 16 ++- .../Record/Model/SenderModelCard.cpp | 121 ++++++++++++++++++ .../Connector/Record/Model/SenderModelCard.h | 80 ++++++++++++ SpeckleLib/Speckle/Database/Content/Record.h | 5 +- SpeckleLib/Speckle/Database/Identity/Index.h | 7 +- SpeckleLib/Speckle/Database/Identity/Link.h | 4 +- .../Speckle/Database/Identity/RecordID.h | 14 ++ .../DocumentStore/DocumentStoreEngine.h | 45 +++---- .../SpeckleLib.xcodeproj/project.pbxproj | 4 + 28 files changed, 561 insertions(+), 126 deletions(-) rename SpeckleConnector/Connector/Database/{Model/Card => }/ModelCardDatabase.cpp (79%) rename SpeckleConnector/Connector/Database/{Model/Card => }/ModelCardDatabase.h (85%) rename SpeckleConnector/Connector/{Database/Model/Card => Record/Model}/CardSetting.cpp (92%) rename SpeckleConnector/Connector/{Database/Model/Card => Record/Model}/CardSetting.h (91%) create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h rename SpeckleConnector/Connector/{Interface/Browser/Bridge/Send/Arg => Record/Model/Filter}/SendFilter.cpp (81%) rename SpeckleConnector/Connector/{Interface/Browser/Bridge/Send/Arg => Record/Model/Filter}/SendFilter.h (56%) rename SpeckleConnector/Connector/{Database/Model/Card => Record/Model}/ModelCard.cpp (93%) rename SpeckleConnector/Connector/{Database/Model/Card => Record/Model}/ModelCard.h (84%) create mode 100644 SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp create mode 100644 SpeckleConnector/Connector/Record/Model/SenderModelCard.h create mode 100644 SpeckleLib/Speckle/Database/Identity/RecordID.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index d96ff81..3f5962f 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -47,12 +47,14 @@ 21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD682C8A0DB40077E104 /* GetIsDevMode.cpp */; }; 21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD8D2C8EE4490077E104 /* Send.cpp */; }; 21D0BD972C8F13F30077E104 /* GetSendFilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */; }; - 21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD982C8F154B0077E104 /* SendFilter.cpp */; }; 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */; }; 21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */; }; 21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */; }; 21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */; }; 21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */; }; + 21D0BDDC2C93897B0077E104 /* SenderModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */; }; + 21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDDD2C9393980077E104 /* SendFilter.cpp */; }; + 21D0BDE32C943C630077E104 /* DirectSelectionSendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */; }; 21D1E9AD2BF14AF200957EAA /* BIMData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9152BF14AEC00957EAA /* BIMData.framework */; }; 21D1E9AE2BF14AF200957EAA /* TeamworkPortalServerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */; }; 21D1E9AF2BF14AF200957EAA /* GDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9172BF14AEC00957EAA /* GDL.framework */; }; @@ -324,8 +326,6 @@ 21D0BD8D2C8EE4490077E104 /* Send.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Send.cpp; sourceTree = ""; }; 21D0BD952C8F13F30077E104 /* GetSendFilters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetSendFilters.h; sourceTree = ""; }; 21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSendFilters.cpp; sourceTree = ""; }; - 21D0BD982C8F154B0077E104 /* SendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendFilter.cpp; sourceTree = ""; }; - 21D0BD992C8F154B0077E104 /* SendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendFilter.h; sourceTree = ""; }; 21D0BDA42C8F33AC0077E104 /* ModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelCard.h; sourceTree = ""; }; 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModelCard.cpp; sourceTree = ""; }; 21D0BDA92C8F363E0077E104 /* CardSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardSetting.h; sourceTree = ""; }; @@ -336,6 +336,12 @@ 21D0BDD32C935D1A0077E104 /* UpdateModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateModel.h; sourceTree = ""; }; 21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveModel.cpp; sourceTree = ""; }; 21D0BDD62C935DAE0077E104 /* RemoveModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveModel.h; sourceTree = ""; }; + 21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SenderModelCard.cpp; sourceTree = ""; }; + 21D0BDDB2C93897B0077E104 /* SenderModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SenderModelCard.h; sourceTree = ""; }; + 21D0BDDD2C9393980077E104 /* SendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendFilter.cpp; sourceTree = ""; }; + 21D0BDDE2C9393980077E104 /* SendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendFilter.h; sourceTree = ""; }; + 21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectSelectionSendFilter.cpp; sourceTree = ""; }; + 21D0BDE22C943C630077E104 /* DirectSelectionSendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectSelectionSendFilter.h; sourceTree = ""; }; 21D1E9152BF14AEC00957EAA /* BIMData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BIMData.framework; path = "../Archicad 27/Support/Frameworks/BIMData.framework"; sourceTree = ""; }; 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TeamworkPortalServerClient.framework; path = "../Archicad 27/Support/Frameworks/TeamworkPortalServerClient.framework"; sourceTree = ""; }; 21D1E9172BF14AEC00957EAA /* GDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GDL.framework; path = "../Archicad 27/Support/Frameworks/GDL.framework"; sourceTree = ""; }; @@ -936,31 +942,11 @@ path = Base; sourceTree = ""; }; - 21B67CC92C77670400FD64FC /* Card */ = { - isa = PBXGroup; - children = ( - 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */, - 21D0BDA92C8F363E0077E104 /* CardSetting.h */, - 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */, - 21D0BDA42C8F33AC0077E104 /* ModelCard.h */, - 21B67CC72C77670400FD64FC /* ModelCardDatabase.cpp */, - 21B67CC82C77670400FD64FC /* ModelCardDatabase.h */, - ); - path = Card; - sourceTree = ""; - }; - 21B67CCA2C77670400FD64FC /* Model */ = { - isa = PBXGroup; - children = ( - 21B67CC92C77670400FD64FC /* Card */, - ); - path = Model; - sourceTree = ""; - }; 21B67CCB2C77670400FD64FC /* Database */ = { isa = PBXGroup; children = ( - 21B67CCA2C77670400FD64FC /* Model */, + 21B67CC72C77670400FD64FC /* ModelCardDatabase.cpp */, + 21B67CC82C77670400FD64FC /* ModelCardDatabase.h */, ); path = Database; sourceTree = ""; @@ -1013,7 +999,6 @@ 21D0BD5D2C89BFEA0077E104 /* Send */ = { isa = PBXGroup; children = ( - 21D0BD9A2C8F154B0077E104 /* Arg */, 21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */, 21D0BD952C8F13F30077E104 /* GetSendFilters.h */, 21D0BD8D2C8EE4490077E104 /* Send.cpp */, @@ -1024,13 +1009,37 @@ path = Send; sourceTree = ""; }; - 21D0BD9A2C8F154B0077E104 /* Arg */ = { + 21D0BDD82C9387E60077E104 /* Record */ = { isa = PBXGroup; children = ( - 21D0BD982C8F154B0077E104 /* SendFilter.cpp */, - 21D0BD992C8F154B0077E104 /* SendFilter.h */, + 21D0BDD92C9387F70077E104 /* Model */, ); - path = Arg; + path = Record; + sourceTree = ""; + }; + 21D0BDD92C9387F70077E104 /* Model */ = { + isa = PBXGroup; + children = ( + 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */, + 21D0BDA92C8F363E0077E104 /* CardSetting.h */, + 21D0BDDF2C9393980077E104 /* Filter */, + 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */, + 21D0BDA42C8F33AC0077E104 /* ModelCard.h */, + 21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */, + 21D0BDDB2C93897B0077E104 /* SenderModelCard.h */, + ); + path = Model; + sourceTree = ""; + }; + 21D0BDDF2C9393980077E104 /* Filter */ = { + isa = PBXGroup; + children = ( + 21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */, + 21D0BDE22C943C630077E104 /* DirectSelectionSendFilter.h */, + 21D0BDDD2C9393980077E104 /* SendFilter.cpp */, + 21D0BDDE2C9393980077E104 /* SendFilter.h */, + ); + path = Filter; sourceTree = ""; }; 21D1EA472BF14B6C00957EAA /* Archicad */ = { @@ -1092,6 +1101,7 @@ 21B67CCB2C77670400FD64FC /* Database */, 21F69F092C677BC0008B6A06 /* Event */, 21F69F0E2C677BC0008B6A06 /* Interface */, + 21D0BDD82C9387E60077E104 /* Record */, 21B67CBA2C774C6500FD64FC /* Version.h */, ); path = Connector; @@ -1353,10 +1363,10 @@ 21B67CE32C78D1FB00FD64FC /* SayHiArg.cpp in Sources */, 21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */, 21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */, - 21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */, 21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */, 21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */, 21B67CF72C78D4DE00FD64FC /* GetComplexType.cpp in Sources */, + 21D0BDDC2C93897B0077E104 /* SenderModelCard.cpp in Sources */, 21B67CAE2C77329800FD64FC /* GetSourceApplicationVersion.cpp in Sources */, 21B67CC32C77649F00FD64FC /* GetDocumentState.cpp in Sources */, 21D0BD602C89BFEA0077E104 /* SendBridge.cpp in Sources */, @@ -1372,6 +1382,7 @@ 21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */, 21B67CE72C78D23B00FD64FC /* ConnectorConfig.cpp in Sources */, 21B67CAD2C77329800FD64FC /* GetSourceApplicationName.cpp in Sources */, + 21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */, 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */, 21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */, 21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */, @@ -1380,6 +1391,7 @@ 21B67CCC2C77670400FD64FC /* ModelCardDatabase.cpp in Sources */, 21F69F132C677BC0008B6A06 /* ConnectorPalette.cpp in Sources */, 21F69FBC2C762EF0008B6A06 /* GetConfig.cpp in Sources */, + 21D0BDE32C943C630077E104 /* DirectSelectionSendFilter.cpp in Sources */, 21B67CF12C78D38000FD64FC /* GoAway.cpp in Sources */, 21F69F142C677BC0008B6A06 /* Connector.cpp in Sources */, ); diff --git a/SpeckleConnector/Connector/Connector.cpp b/SpeckleConnector/Connector/Connector.cpp index 09489cd..4306b0b 100755 --- a/SpeckleConnector/Connector/Connector.cpp +++ b/SpeckleConnector/Connector/Connector.cpp @@ -1,7 +1,7 @@ #include "Active/File/Directory.h" #include "ConnectorResource.h" #include "Connector/Connector.h" -#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Database/ModelCardDatabase.h" #include "Interface/ConnectorMenu.h" #include "Interface/ConnectorPalette.h" #include "Speckle/Database/AccountDatabase.h" diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp similarity index 79% rename from SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp rename to SpeckleConnector/Connector/Database/ModelCardDatabase.cpp index aa6175b..0ad0d9e 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp @@ -1,33 +1,35 @@ -#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Database/ModelCardDatabase.h" #include "Active/Database/Storage/Storage.h" #include "Active/Serialise/JSON/JSONTransport.h" +#include "Speckle/Database/Identity/RecordID.h" #include "Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h" #include using namespace active::container; using namespace active::database; +using namespace active::event; using namespace active::serialise; using namespace active::serialise::json; -using namespace active::setting; using namespace connector::database; +using namespace connector::record; using namespace speckle::database; using namespace speckle::utility; namespace connector::database { ///ModelCard database engine declaration - class ModelCardDatabase::Engine : public DocumentStoreEngine { - using base = DocumentStoreEngine; + class ModelCardDatabase::Engine : public DocumentStoreEngine { + using base = DocumentStoreEngine; using base::base; }; ///ModelCard database storage declaration - class ModelCardDatabase::Store : public active::database::Storage { - using base = active::database::Storage; + class ModelCardDatabase::Store : public Storage { + using base = Storage; using base::base; }; @@ -93,7 +95,7 @@ void ModelCardDatabase::write(const ModelCard& card) const { cardID: The ID of the card to erase --------------------------------------------------------------------*/ -void ModelCardDatabase::erase(const speckle::utility::String& cardID) const { +void ModelCardDatabase::erase(const String& cardID) const { m_store->erase(cardID); } //ModelCardDatabase::erase @@ -114,5 +116,5 @@ std::unique_ptr ModelCardDatabase::wrapper() const { return: The database subscription (add weakly to publisher) --------------------------------------------------------------------*/ std::shared_ptr ModelCardDatabase::getSubscription() { - return std::dynamic_pointer_cast(m_engine); + return std::dynamic_pointer_cast(m_engine); } //ModelCardDatabase::getSubscription diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h b/SpeckleConnector/Connector/Database/ModelCardDatabase.h similarity index 85% rename from SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h rename to SpeckleConnector/Connector/Database/ModelCardDatabase.h index 90a770b..d2e7db6 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCardDatabase.h +++ b/SpeckleConnector/Connector/Database/ModelCardDatabase.h @@ -1,7 +1,7 @@ #ifndef CONNECTOR_DATABASE_MODEL_CARD_DATABASE #define CONNECTOR_DATABASE_MODEL_CARD_DATABASE -#include "Connector/Database/Model/Card/ModelCard.h" +#include "Connector/Record/Model/ModelCard.h" namespace active::event { class Subscriber; @@ -33,12 +33,12 @@ namespace connector::database { Get all model cards @return All the cards */ - active::container::Vector getCards() const; + active::container::Vector getCards() const; /*! Write a card to storage @param card The card to write */ - void write(const ModelCard& card) const; + void write(const record::ModelCard& card) const; /*! Erase a card @param cardID The ID of the card to erase diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp index 262be5c..daa5299 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp @@ -1,12 +1,12 @@ #include "Connector/Interface/Browser/Bridge/Base/AddModel.h" #include "Connector/Connector.h" -#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Database/ModelCardDatabase.h" #include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" using namespace active::container; using namespace active::serialise; -using namespace connector::database; +using namespace connector::record; using namespace connector::interfac::browser::bridge; using namespace speckle::utility; diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h index 1816944..4573486 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h @@ -3,13 +3,13 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" -#include "Connector/Database/Model/Card/ModelCard.h" +#include "Connector/Record/Model/ModelCard.h" #include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" namespace connector::interfac::browser::bridge { ///Argument parameter for a string - using CardHold = active::serialise::CargoHold; + using CardHold = active::serialise::CargoHold; ///Argument type for this method using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType; @@ -32,7 +32,7 @@ namespace connector::interfac::browser::bridge { Add a model card to document storage @param card The card to add */ - void run(connector::database::ModelCard& card) const; + void run(connector::record::ModelCard& card) const; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp index beccf4e..b0ecc18 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp @@ -3,13 +3,14 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/ContainerWrap.h" #include "Connector/Connector.h" -#include "Connector/Database/Model/Card/ModelCard.h" -#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Record/Model/ModelCard.h" +#include "Connector/Database/ModelCardDatabase.h" using namespace active::container; using namespace active::serialise; using namespace connector::interfac::browser::bridge; using namespace connector::database; +using namespace connector::record; using namespace speckle::utility; namespace { diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp index ca7d0e7..d6dd2f4 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp @@ -1,12 +1,13 @@ #include "Connector/Interface/Browser/Bridge/Base/RemoveModel.h" #include "Connector/Connector.h" -#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Database/ModelCardDatabase.h" #include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" using namespace active::container; using namespace active::serialise; using namespace connector::database; +using namespace connector::record; using namespace connector::interfac::browser::bridge; using namespace speckle::utility; diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h index 00c8aab..dbdc99a 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h @@ -3,13 +3,13 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" -#include "Connector/Database/Model/Card/ModelCard.h" +#include "Connector/Record/Model/ModelCard.h" #include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" namespace connector::interfac::browser::bridge { ///Argument parameter for a string - using CardHold = active::serialise::CargoHold; + using CardHold = active::serialise::CargoHold; ///Argument type for this method using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType; @@ -32,7 +32,7 @@ namespace connector::interfac::browser::bridge { Add a model card to document storage @param card The card to add */ - void run(connector::database::ModelCard& card) const; + void run(connector::record::ModelCard& card) const; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp index 301349a..7fcd02c 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp @@ -1,12 +1,13 @@ #include "Connector/Interface/Browser/Bridge/Base/UpdateModel.h" #include "Connector/Connector.h" -#include "Connector/Database/Model/Card/ModelCardDatabase.h" +#include "Connector/Database/ModelCardDatabase.h" #include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h" using namespace active::container; using namespace active::serialise; using namespace connector::database; +using namespace connector::record; using namespace connector::interfac::browser::bridge; using namespace speckle::utility; diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h index 41ea93b..cbca60a 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h @@ -3,13 +3,13 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" -#include "Connector/Database/Model/Card/ModelCard.h" +#include "Connector/Record/Model/ModelCard.h" #include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" namespace connector::interfac::browser::bridge { ///Argument parameter for a string - using CardHold = active::serialise::CargoHold; + using CardHold = active::serialise::CargoHold; ///Argument type for this method using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType; @@ -32,7 +32,7 @@ namespace connector::interfac::browser::bridge { Add a model card to document storage @param card The card to add */ - void run(connector::database::ModelCard& card) const; + void run(connector::record::ModelCard& card) const; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp index 6897267..4f16d00 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp @@ -4,10 +4,11 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/ContainerWrap.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" -#include "Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h" +#include "Connector/Record/Model/Filter/SendFilter.h" using namespace active::container; using namespace active::serialise; +using namespace connector::record; using namespace connector::interfac::browser::bridge; using namespace speckle::utility; diff --git a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp b/SpeckleConnector/Connector/Record/Model/CardSetting.cpp similarity index 92% rename from SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp rename to SpeckleConnector/Connector/Record/Model/CardSetting.cpp index e38db56..ecd1fc1 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.cpp +++ b/SpeckleConnector/Connector/Record/Model/CardSetting.cpp @@ -1,4 +1,4 @@ -#include "Connector/Database/Model/Card/CardSetting.h" +#include "Connector/Record/Model/CardSetting.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Active/Serialise/Item/Wrapper/AnyValueWrap.h" @@ -6,7 +6,7 @@ #include using namespace active::serialise; -using namespace connector::database; +using namespace connector::record; using namespace speckle::utility; namespace { diff --git a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h b/SpeckleConnector/Connector/Record/Model/CardSetting.h similarity index 91% rename from SpeckleConnector/Connector/Database/Model/Card/CardSetting.h rename to SpeckleConnector/Connector/Record/Model/CardSetting.h index 37ca2da..281528b 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/CardSetting.h +++ b/SpeckleConnector/Connector/Record/Model/CardSetting.h @@ -1,5 +1,5 @@ -#ifndef CONNECTOR_DATABASE_MODEL_CARD_SETTING -#define CONNECTOR_DATABASE_MODEL_CARD_SETTING +#ifndef CONNECTOR_RECORD_CARD_SETTING +#define CONNECTOR_RECORD_CARD_SETTING #include "Active/Serialise/Package/Package.h" #include "Active/Setting/ValueSetting.h" @@ -8,7 +8,7 @@ #include "Speckle/Utility/Guid.h" #include "Speckle/Utility/String.h" -namespace connector::database { +namespace connector::record { /*! A setting attached to a model card, capturing rendering/view states of the model at the time of sending, e.g. level of detail (LoD) @@ -104,4 +104,4 @@ namespace connector::database { } -#endif //CONNECTOR_DATABASE_MODEL_CARD_SETTING +#endif //CONNECTOR_RECORD_CARD_SETTING diff --git a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp new file mode 100644 index 0000000..25563fd --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp @@ -0,0 +1,80 @@ +#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" + +#include + +using namespace active::serialise; +using namespace connector::record; +using namespace speckle::utility; + +namespace { + + ///Serialisation fields + enum FieldIndex { + nameID, + summaryID, + defaultID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"name"}, + Identity{"summary"}, + Identity{"isDefault"}, + }; + +} + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool DirectSelectionSendFilter::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[nameID], nameID, element }, + { fieldID[summaryID], summaryID, element }, + { fieldID[defaultID], defaultID, element }, + }, + }.withType(&typeid(DirectSelectionSendFilter))); + return true; +} //DirectSelectionSendFilter::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique DirectSelectionSendFilter::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(DirectSelectionSendFilter)) + return nullptr; + using namespace active::serialise; + switch (item.index) { + case nameID: + return std::make_unique>(m_name); + case summaryID: + return std::make_unique>(m_summary); + case defaultID: + return std::make_unique>(m_isDefault); + default: + return nullptr; //Requested an unknown index + } +} //DirectSelectionSendFilter::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void DirectSelectionSendFilter::setDefault() { + m_name.clear(); + m_summary.clear(); + m_isDefault = false; +} //DirectSelectionSendFilter::setDefault diff --git a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h new file mode 100644 index 0000000..18e8d0d --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h @@ -0,0 +1,88 @@ +#ifndef CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER +#define CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER + +#include "Active/Serialise/Package/Package.h" +#include "Active/Utility/Cloner.h" +#include "Speckle/Utility/String.h" + +namespace connector::record { + + /*! + Base class for element filters applied when a model is sent to a Speckle server + */ + class DirectSelectionSendFilter : public active::serialise::Package, public active::utility::Cloner { + public: + + // MARK: - Types + + using base = active::serialise::Package; + + // MARK: - Constructors + + /*! + Default constructor + @param nm The filter name + @param sum A summary + @param isDef True if this is the default filter + */ + DirectSelectionSendFilter(const speckle::utility::String& nm = {}, const speckle::utility::String& sum = {}, bool isDef = false) : + m_name{nm}, m_summary{sum}, m_isDefault{isDef} {} + /*! + Destructor + */ + virtual ~DirectSelectionSendFilter() {} + /*! + Record cloning + @return A clone of this record + */ + virtual DirectSelectionSendFilter* clonePtr() const override { return new DirectSelectionSendFilter(*this); }; + + // MARK: - Functions (const) + + /*! + Get the filter name + @return The filter name + */ + const speckle::utility::String& getName() const { return m_name; }; + /*! + Get a summary description of the filter function, e.g. "All selected elements" + @return The filter summary description + */ + const speckle::utility::String& getSummary() const { return m_name; }; + /*! + Determine if this is the default filter for model sends + @return True if this is the default filter + */ + bool isDefault() const { return m_isDefault; }; + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + ///The filter name + speckle::utility::String m_name; + ///A summary + speckle::utility::String m_summary; + ///True if this is the default filter + bool m_isDefault = false; + }; + +} + +#endif //CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp similarity index 81% rename from SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.cpp rename to SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp index 8abef93..08a17e8 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.cpp +++ b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp @@ -1,11 +1,11 @@ -#include "Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h" +#include "Connector/Record/Model/Filter/SendFilter.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include using namespace active::serialise; -using namespace connector::interfac::browser::bridge; +using namespace connector::record; using namespace speckle::utility; namespace { @@ -59,11 +59,11 @@ Cargo::Unique SendFilter::getCargo(const Inventory::Item& item) const { using namespace active::serialise; switch (item.index) { case nameID: - return std::make_unique>(name); + return std::make_unique>(m_name); case summaryID: - return std::make_unique>(summary); + return std::make_unique>(m_summary); case defaultID: - return std::make_unique>(isDefault); + return std::make_unique>(m_isDefault); default: return nullptr; //Requested an unknown index } @@ -74,7 +74,7 @@ Cargo::Unique SendFilter::getCargo(const Inventory::Item& item) const { Set to the default package content --------------------------------------------------------------------*/ void SendFilter::setDefault() { - name.clear(); - summary.clear(); - isDefault = false; + m_name.clear(); + m_summary.clear(); + m_isDefault = false; } //SendFilter::setDefault diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h similarity index 56% rename from SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h rename to SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h index d86abc6..fc0e0dd 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h +++ b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h @@ -1,14 +1,14 @@ -#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_FILTER -#define CONNECTOR_INTERFACE_BRIDGE_SEND_FILTER +#ifndef CONNECTOR_RECORD_SEND_FILTER +#define CONNECTOR_RECORD_SEND_FILTER #include "Active/Serialise/Package/Package.h" #include "Active/Utility/Cloner.h" #include "Speckle/Utility/String.h" -namespace connector::interfac::browser::bridge { +namespace connector::record { /*! - A connector send filter + Base class for element filters applied when a model is sent to a Speckle server */ class SendFilter : public active::serialise::Package, public active::utility::Cloner { public: @@ -26,22 +26,35 @@ namespace connector::interfac::browser::bridge { @param isDef True if this is the default filter */ SendFilter(const speckle::utility::String& nm = {}, const speckle::utility::String& sum = {}, bool isDef = false) : - name{nm}, summary{sum}, isDefault{isDef} {} + m_name{nm}, m_summary{sum}, m_isDefault{isDef} {} + /*! + Destructor + */ + virtual ~SendFilter() {} /*! Record cloning @return A clone of this record */ virtual SendFilter* clonePtr() const override { return new SendFilter(*this); }; - - // MARK: - Public variables (NB: Assuming to class invariants or overrides for this data, so making public for simplicity) - - ///The filter name - speckle::utility::String name; - ///A summary - speckle::utility::String summary; - ///True if this is the default filter - bool isDefault = false; + // MARK: - Functions (const) + + /*! + Get the filter name + @return The filter name + */ + const speckle::utility::String& getName() const { return m_name; }; + /*! + Get a summary description of the filter function, e.g. "All selected elements" + @return The filter summary description + */ + const speckle::utility::String& getSummary() const { return m_name; }; + /*! + Determine if this is the default filter for model sends + @return True if this is the default filter + */ + bool isDefault() const { return m_isDefault; }; + // MARK: - Serialisation /*! @@ -60,8 +73,16 @@ namespace connector::interfac::browser::bridge { Set to the default package content */ void setDefault() override; + + private: + ///The filter name + speckle::utility::String m_name; + ///A summary + speckle::utility::String m_summary; + ///True if this is the default filter + bool m_isDefault = false; }; } -#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_FILTER +#endif //CONNECTOR_RECORD_SEND_FILTER diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp b/SpeckleConnector/Connector/Record/Model/ModelCard.cpp similarity index 93% rename from SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp rename to SpeckleConnector/Connector/Record/Model/ModelCard.cpp index 17ae829..3f7dcce 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.cpp +++ b/SpeckleConnector/Connector/Record/Model/ModelCard.cpp @@ -1,4 +1,4 @@ -#include "Connector/Database/Model/Card/ModelCard.h" +#include "Connector/Record/Model/ModelCard.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Active/Serialise/Package/Wrapper/ContainerWrap.h" @@ -7,7 +7,7 @@ using namespace active::container; using namespace active::serialise; -using namespace connector::database; +using namespace connector::record; using namespace speckle::utility; namespace { diff --git a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h b/SpeckleConnector/Connector/Record/Model/ModelCard.h similarity index 84% rename from SpeckleConnector/Connector/Database/Model/Card/ModelCard.h rename to SpeckleConnector/Connector/Record/Model/ModelCard.h index d0d249e..6503753 100644 --- a/SpeckleConnector/Connector/Database/Model/Card/ModelCard.h +++ b/SpeckleConnector/Connector/Record/Model/ModelCard.h @@ -1,14 +1,14 @@ -#ifndef CONNECTOR_DATABASE_MODEL_CARD -#define CONNECTOR_DATABASE_MODEL_CARD +#ifndef CONNECTOR_RECORD_MODEL_CARD +#define CONNECTOR_RECORD_MODEL_CARD #include "Active/Container/Vector.h" #include "Active/Serialise/Package/Package.h" #include "Active/Utility/Cloner.h" -#include "Connector/Database/Model/Card/CardSetting.h" +#include "Connector/Record/Model/CardSetting.h" #include "Speckle/Utility/String.h" #include "Speckle/Database/Content/Record.h" -namespace connector::database { +namespace connector::record { /*! A connector send filter @@ -20,7 +20,7 @@ namespace connector::database { using base = speckle::database::Record; //List of card settings - using SettingList = active::container::Vector; + using SettingList = active::container::Vector; // MARK: - Constructors @@ -28,6 +28,10 @@ namespace connector::database { Default constructor */ ModelCard() {} + /*! + Destructor + */ + virtual ~ModelCard() {} /*! Record cloning @return A clone of this record @@ -96,4 +100,4 @@ namespace connector::database { } -#endif //CONNECTOR_DATABASE_MODEL_CARD +#endif //CONNECTOR_RECORD_MODEL_CARD diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp new file mode 100644 index 0000000..4db1090 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp @@ -0,0 +1,121 @@ +#include "Connector/Record/Model/SenderModelCard.h" + +#include "Connector/Record/Model/Filter/SendFilter.h" + +#include + +using namespace active::serialise; +using namespace connector::record; +using namespace speckle::utility; + +namespace { + + ///Serialisation fields + enum FieldIndex { + sendFilterID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"sendFilter"}, + }; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +SenderModelCard::SenderModelCard() { + +} //SenderModelCard::SenderModelCard + + +/*-------------------------------------------------------------------- + Constructor + + filter: The filter applied when the model was sent + --------------------------------------------------------------------*/ +SenderModelCard::SenderModelCard(const SendFilter& filter) { + +} //SenderModelCard::SenderModelCard + + +/*-------------------------------------------------------------------- + Copy constructor + + source: The object to copy + --------------------------------------------------------------------*/ +SenderModelCard::SenderModelCard(const SenderModelCard& source) { + +} //SenderModelCard::SenderModelCard + + +/*-------------------------------------------------------------------- + Destructor + --------------------------------------------------------------------*/ +SenderModelCard::~SenderModelCard() { + +} //SenderModelCard::~SenderModelCard + + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool SenderModelCard::fillInventory(Inventory& inventory) const { + using enum Entry::Type; +/* inventory.merge(Inventory{ + { + { fieldID[modelID], modelID, element }, + { fieldID[projectID], projectID, element }, + { fieldID[accountID], accountID, element }, + { fieldID[serverURLID], serverURLID, element }, + { fieldID[settingsID], settingsID, element }, + }, + }.withType(&typeid(SenderModelCard))); + return base::fillInventory(inventory);*/ +} //SenderModelCard::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique SenderModelCard::getCargo(const Inventory::Item& item) const { +/* if (item.ownerType != &typeid(SenderModelCard)) + return base::getCargo(item); + using namespace active::serialise; + switch (item.index) { + case modelID: + return std::make_unique>(m_modelID); + case projectID: + return std::make_unique>(m_projectID); + case accountID: + return std::make_unique>(m_accountID); + case serverURLID: + return std::make_unique>(m_serverURL); + case settingsID: + return std::make_unique>(m_settings); + default: + return nullptr; //Requested an unknown index + }*/ +} //SenderModelCard::getCargo + + +/*-------------------------------------------------------------------- + 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();*/ +} //SenderModelCard::setDefault diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.h b/SpeckleConnector/Connector/Record/Model/SenderModelCard.h new file mode 100644 index 0000000..16d3493 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.h @@ -0,0 +1,80 @@ +#ifndef CONNECTOR_RECORD_SENDER_MODEL_CARD +#define CONNECTOR_RECORD_SENDER_MODEL_CARD + +#include "Connector/Record/Model/ModelCard.h" + +namespace connector::record { + + class SendFilter; + + /*! + A connector model send card - carries information about what was sent with the model + */ + class SenderModelCard : public connector::record::ModelCard { + public: + + // MARK: - Types + + using base = connector::record::ModelCard; + + // MARK: - Constructors + + /*! + Default constructor + */ + SenderModelCard(); + /*! + Constructor + @param filter The filter applied when the model was sent + */ + SenderModelCard(const SendFilter& filter); + /*! + Copy constructor + @param source The object to copy + */ + SenderModelCard(const SenderModelCard& source); + /*! + Destructor + */ + ~SenderModelCard(); + /*! + Record cloning + @return A clone of this record + */ + virtual SenderModelCard* clonePtr() const override { return new SenderModelCard(*this); }; + + // MARK: - Functions (const) + + /*! + Get the filter applied when the model was sent + @return The model filter + */ + const SendFilter& getFilter() const { return *m_filter; } + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + ///The filter applied when the model was sent + std::unique_ptr m_filter; + }; + +} + +#endif //CONNECTOR_RECORD_SENDER_MODEL_CARD diff --git a/SpeckleLib/Speckle/Database/Content/Record.h b/SpeckleLib/Speckle/Database/Content/Record.h index 6a99d6e..fdd1b3c 100644 --- a/SpeckleLib/Speckle/Database/Content/Record.h +++ b/SpeckleLib/Speckle/Database/Content/Record.h @@ -3,18 +3,19 @@ #include "Active/Database/Content/Record.h" #include "Speckle/Database/Identity/Link.h" +#include "Speckle/Database/Identity/RecordID.h" namespace speckle::database { /*! Base class for a database record */ - class Record : public active::database::Record { + class Record : public active::database::Record { public: // MARK: - Types - using base = active::database::Record; + using base = active::database::Record; ///Unique pointer using Unique = std::unique_ptr; ///Shared pointer diff --git a/SpeckleLib/Speckle/Database/Identity/Index.h b/SpeckleLib/Speckle/Database/Identity/Index.h index 8b49749..c3b3e66 100644 --- a/SpeckleLib/Speckle/Database/Identity/Index.h +++ b/SpeckleLib/Speckle/Database/Identity/Index.h @@ -2,8 +2,11 @@ #define SPECKLE_DATABASE_INDEX #include "Active/Database/Identity/Link.h" +#include "Speckle/Database/Identity/RecordID.h" #include "Speckle/Utility/String.h" +#include + namespace speckle::database { /*! @@ -13,12 +16,12 @@ namespace speckle::database { this is typically a guid, for Revit a string and for Vectorworks a handle. Note that this index is not necessarily persistent between sessions. */ - class Index : public active::database::Index { + class Index : public active::database::Index { public: // MARK: - Types - using base = active::database::Index; + using base = active::database::Index; // MARK: - Constructors diff --git a/SpeckleLib/Speckle/Database/Identity/Link.h b/SpeckleLib/Speckle/Database/Identity/Link.h index dc6624b..2789d22 100644 --- a/SpeckleLib/Speckle/Database/Identity/Link.h +++ b/SpeckleLib/Speckle/Database/Identity/Link.h @@ -17,12 +17,12 @@ namespace speckle::database { A link may optionally carry any number of settings. In the context of a user selection (for example) there might be settings describing where the user made the selection (e.g. the hole in a floor slab), allowing a tool working on that selection to be more precise. */ - class Link : public active::database::Link { + class Link : public active::database::Link { public: // MARK: - Types - using base = active::database::Link; + using base = active::database::Link; // MARK: - Constructors diff --git a/SpeckleLib/Speckle/Database/Identity/RecordID.h b/SpeckleLib/Speckle/Database/Identity/RecordID.h new file mode 100644 index 0000000..1a8267f --- /dev/null +++ b/SpeckleLib/Speckle/Database/Identity/RecordID.h @@ -0,0 +1,14 @@ +#ifndef SPECKLE_DATABASE_ID +#define SPECKLE_DATABASE_ID + +#include "Speckle/Utility/String.h" + +namespace speckle::database { + + using RecordID = speckle::utility::String; + using TableID = speckle::utility::String; + using DBaseID = speckle::utility::String; + +} + +#endif //SPECKLE_DATABASE_ID diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index 978b1c7..fc42f83 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -11,6 +11,7 @@ #include "Active/Utility/BufferIn.h" #include "Active/Utility/BufferOut.h" #include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h" +#include "Speckle/Database/Identity/RecordID.h" #include "Speckle/Utility/Guid.h" #include "Speckle/Utility/String.h" @@ -34,17 +35,17 @@ namespace speckle::database { @tparam Transport The serialisation transport mechanism for objects @tparam ObjID The object identifier type, e.g. Guid */ - template + template requires DocumentStorable - class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { + class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { public: // MARK: - Types - using base = active::database::DBaseEngine; + using base = active::database::DBaseEngine; using Filter = base::Filter; using Outline = base::Outline; - using Cache = active::database::RecordCache; + using Cache = active::database::RecordCache; // MARK: - Constructors @@ -64,14 +65,14 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) @return The requested object (nullptr on failure) */ - std::unique_ptr getObject(const ObjID& objID, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; + std::unique_ptr getObject(const ObjID& objID, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Get all objects @param tableID Optional table ID (defaults to the first table) @param documentID Optional document ID (filter for this document only - nullopt = all objects) @return The requested objects (nullptr on failure) */ - active::container::Vector getObjects(std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; + active::container::Vector getObjects(std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Get a filtered list of objects @param filter The object filter @@ -79,8 +80,8 @@ namespace speckle::database { @param documentID Optional document ID (filter for this document only - nullopt = all objects) @return The filtered objects (nullptr on failure) */ - active::container::Vector getObjects(const Filter& filter, std::optional tableID = std::nullopt, - std::optional documentID = std::nullopt) const override; + active::container::Vector getObjects(const Filter& filter, std::optional tableID = std::nullopt, + std::optional documentID = std::nullopt) const override; /*! Write an object to the database @param object The object to write @@ -90,7 +91,7 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) */ void write(const Obj& object, const ObjID& objID, std::optional objDocID = std::nullopt, - utility::String::Option tableID = std::nullopt, utility::String::Option documentID = std::nullopt) const override; + std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Erase an object by index @param ID The object ID @@ -98,15 +99,15 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) @throw Exception thrown on SQL error */ - void erase(const ObjID& ID, std::optional tableID = std::nullopt, - std::optional documentID = std::nullopt) const override; + void erase(const ObjID& ID, std::optional tableID = std::nullopt, + std::optional documentID = std::nullopt) const override; /*! Erase all objects @param tableID Optional table ID (defaults to the first table) @param documentID Optional document ID (when the object is bound to a specific document) @throw Exception thrown on SQL error */ - void erase(std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; + void erase(std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override; /*! Get the database outline @return The database outline @@ -175,8 +176,8 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, std::optional tableID, - std::optional documentID) const { + std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, std::optional tableID, + std::optional documentID) const { return getCache()->read(ID); } //DocumentStoreEngine::getObject @@ -191,8 +192,8 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - active::container::Vector DocumentStoreEngine::getObjects(std::optional tableID, - std::optional documentID) const { + active::container::Vector DocumentStoreEngine::getObjects(std::optional tableID, + std::optional documentID) const { return getCache()->read(); } //DocumentStoreEngine::getObjects @@ -208,8 +209,8 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, std::optional tableID, - std::optional documentID) const { + active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, std::optional tableID, + std::optional documentID) const { return getCache()->read(filter); } //DocumentStoreEngine::getObjects @@ -226,7 +227,7 @@ namespace speckle::database { template requires DocumentStorable void DocumentStoreEngine::write(const Obj& object, const ObjID& objID, std::optional objDocID, - utility::String::Option tableID, utility::String::Option documentID) const { + std::optional tableID, std::optional documentID) const { getCache()->write(object); //NB: In future we might support duplicating records if objID != obj.id } //DocumentStoreEngine::write @@ -242,8 +243,8 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - void DocumentStoreEngine::erase(const ObjID& ID, std::optional tableID, - std::optional documentID) const { + void DocumentStoreEngine::erase(const ObjID& ID, std::optional tableID, + std::optional documentID) const { getCache()->erase(ID); } //DocumentStoreEngine::erase @@ -256,7 +257,7 @@ namespace speckle::database { --------------------------------------------------------------------*/ template requires DocumentStorable - void DocumentStoreEngine::erase(std::optional tableID, std::optional documentID) const { + void DocumentStoreEngine::erase(std::optional tableID, std::optional documentID) const { getCache()->erase(); } //DocumentStoreEngine::erase diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj index b25bb9a..0953228 100644 --- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj +++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ 21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */; }; 21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */; }; 21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */; }; + 21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDE42C943D3F0077E104 /* RecordID.h */; }; 21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F382C6B880B008B6A06 /* JSBaseTransport.cpp */; }; 21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */; }; 21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F602C6D0286008B6A06 /* GetBindingsMethodNames.cpp */; }; @@ -146,6 +147,7 @@ 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectSubscriber.cpp; sourceTree = ""; }; 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectSubscriber.h; sourceTree = ""; }; 21D0BDC62C9245E40077E104 /* ProjectEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectEvent.h; sourceTree = ""; }; + 21D0BDE42C943D3F0077E104 /* RecordID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordID.h; sourceTree = ""; }; 21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = ""; }; 21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = ""; }; 21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = ""; }; @@ -335,6 +337,7 @@ 21D0BD2D2C86FE090077E104 /* Index.h */, 21D0BD2E2C86FE090077E104 /* Link.cpp */, 21D0BD2F2C86FE090077E104 /* Link.h */, + 21D0BDE42C943D3F0077E104 /* RecordID.h */, ); path = Identity; sourceTree = ""; @@ -476,6 +479,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */, 21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */, 210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */, 210CC8A02C81E34400610F58 /* Platform.h in Headers */, From e75ef3133d553937885d76c656a744c20ea38cf5 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Sat, 14 Sep 2024 02:06:02 +0100 Subject: [PATCH 10/16] 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) --- .../Connector.xcodeproj/project.pbxproj | 12 ++++ .../Connector/Database/ModelCardDatabase.cpp | 5 +- .../Connector/Record/Model/CardMover.cpp | 56 ++++++++++++++++ .../Connector/Record/Model/CardMover.h | 41 ++++++++++++ .../Record/Model/Filter/FilterMover.cpp | 64 +++++++++++++++++++ .../Record/Model/Filter/FilterMover.h | 51 +++++++++++++++ .../Record/Model/SenderModelCard.cpp | 37 ++++------- .../DocumentStore/DocumentStoreEngine.h | 30 +++++---- .../Speckle/Record/Credentials/ServerInfo.cpp | 5 +- 9 files changed, 258 insertions(+), 43 deletions(-) create mode 100644 SpeckleConnector/Connector/Record/Model/CardMover.cpp create mode 100644 SpeckleConnector/Connector/Record/Model/CardMover.h create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index 3f5962f..273a6d9 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ""; }; + 215F08292C947F4400CD343B /* CardMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardMover.h; sourceTree = ""; }; + 215F082C2C94C5C000CD343B /* FilterMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilterMover.cpp; sourceTree = ""; }; + 215F082D2C94C5C000CD343B /* FilterMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterMover.h; sourceTree = ""; }; 2161FD902BF2600C006D9527 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 219388682C4E5DE2002A0180 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 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 */, diff --git a/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp index 0ad0d9e..d53c689 100644 --- a/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp @@ -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 { - using base = DocumentStoreEngine; + class ModelCardDatabase::Engine : public DocumentStoreEngine { + using base = DocumentStoreEngine; using base::base; }; diff --git a/SpeckleConnector/Connector/Record/Model/CardMover.cpp b/SpeckleConnector/Connector/Record/Model/CardMover.cpp new file mode 100644 index 0000000..841e05b --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/CardMover.cpp @@ -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 CardMover::m_handler = std::make_shared(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(senderCardTypeName); +} //CardMover::validateHandler diff --git a/SpeckleConnector/Connector/Record/Model/CardMover.h b/SpeckleConnector/Connector/Record/Model/CardMover.h new file mode 100644 index 0000000..09ec860 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/CardMover.h @@ -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 m_handler; + }; + +} + +#endif //CONNECTOR_MODEL_CARD_MOVER diff --git a/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp new file mode 100644 index 0000000..5712d2d --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp @@ -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 FilterMover::m_handler = std::make_shared(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(DirectSelectionTypeName); +} //FilterMover::validateHandler diff --git a/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h new file mode 100644 index 0000000..48e13a1 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h @@ -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 m_handler; + }; + +} + +#endif //CONNECTOR_MODEL_SEND_FILTER_MOVER diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp index 4db1090..08e1d8b 100644 --- a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp +++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp @@ -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 @@ -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>(m_modelID); - case projectID: - return std::make_unique>(m_projectID); - case accountID: - return std::make_unique>(m_accountID); - case serverURLID: - return std::make_unique>(m_serverURL); - case settingsID: - return std::make_unique>(m_settings); + case sendFilterID: + return std::make_unique(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 diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index fc42f83..9ec72f7 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -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 - concept DocumentStorable = std::is_base_of_v && + template + concept DocumentStorable = (active::database::CanWrap || active::database::FlatType) && + std::is_base_of_v && std::is_base_of_v; /*! @@ -36,7 +38,7 @@ namespace speckle::database { @tparam ObjID The object identifier type, e.g. Guid */ template - requires DocumentStorable + requires DocumentStorable class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine { public: @@ -45,7 +47,7 @@ namespace speckle::database { using base = active::database::DBaseEngine; using Filter = base::Filter; using Outline = base::Outline; - using Cache = active::database::RecordCache; + using Cache = active::database::RecordCache; // MARK: - Constructors @@ -147,7 +149,7 @@ namespace speckle::database { return: The cached records (nullptr on failure) --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable typename DocumentStoreEngine::Cache* DocumentStoreEngine::getCache() const { if (m_cache) return m_cache.get(); @@ -175,7 +177,7 @@ namespace speckle::database { return: The requested object (nullptr on failure) --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable std::unique_ptr DocumentStoreEngine::getObject(const ObjID& ID, std::optional tableID, std::optional documentID) const { return getCache()->read(ID); @@ -191,7 +193,7 @@ namespace speckle::database { return: The requested objects (nullptr on failure) --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable active::container::Vector DocumentStoreEngine::getObjects(std::optional tableID, std::optional documentID) const { return getCache()->read(); @@ -208,7 +210,7 @@ namespace speckle::database { return: The requested objects (nullptr on failure) --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable active::container::Vector DocumentStoreEngine::getObjects(const Filter& filter, std::optional tableID, std::optional 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 - requires DocumentStorable + requires DocumentStorable void DocumentStoreEngine::write(const Obj& object, const ObjID& objID, std::optional objDocID, std::optional tableID, std::optional 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 - requires DocumentStorable + requires DocumentStorable void DocumentStoreEngine::erase(const ObjID& ID, std::optional tableID, std::optional 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 - requires DocumentStorable + requires DocumentStorable void DocumentStoreEngine::erase(std::optional tableID, std::optional documentID) const { getCache()->erase(); } //DocumentStoreEngine::erase @@ -268,7 +270,7 @@ namespace speckle::database { return: The database outline --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable DocumentStoreEngine::Outline DocumentStoreEngine::getOutline() const { Outline result; if (getSchema().empty()) @@ -285,7 +287,7 @@ namespace speckle::database { return: Data to store from the latest records --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable active::utility::Memory DocumentStoreEngine::buildStore() { active::utility::Memory result; Transport().send(std::forward(*getCache()), active::serialise::Identity{}, result); @@ -301,7 +303,7 @@ namespace speckle::database { return: The merged data to be stored --------------------------------------------------------------------*/ template - requires DocumentStorable + requires DocumentStorable void DocumentStoreEngine::mergeStore(const active::utility::Memory& toMerge) { //Import the incoming records from the data to merge Cache incoming; diff --git a/SpeckleLib/Speckle/Record/Credentials/ServerInfo.cpp b/SpeckleLib/Speckle/Record/Credentials/ServerInfo.cpp index db98ce8..9a237e5 100644 --- a/SpeckleLib/Speckle/Record/Credentials/ServerInfo.cpp +++ b/SpeckleLib/Speckle/Record/Credentials/ServerInfo.cpp @@ -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 @@ -90,7 +91,7 @@ Cargo::Unique ServerInfo::getCargo(const Inventory::Item& item) const { case urlID: return std::make_unique(m_url); case migrationID: - return std::make_unique>(m_migration); + return std::make_unique(PackageUniqueWrap{m_migration}); default: return nullptr; //Requested an unknown index } From e92729e10f8f7434fe75a1b08fa8e5b47181aaa0 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Sun, 15 Sep 2024 22:23:12 +0100 Subject: [PATCH 11/16] Added RecordID to express common ID types for Archicad Added ArchicadEverythingFilter Added ArchicadSelectionFilter Added EverythingSendFilter Updated SendFilter bridge method with defined filter types Updated FilterMover with defined filter types Implemented SendFilter::checkExpiry Updated CardMover with ReceiverModelCard Updated all bridge method args as const reference --- .../Connector.xcodeproj/project.pbxproj | 26 ++++ .../Connector/Database/Identity/RecordID.h | 16 +++ .../Browser/Bridge/Account/GetAccounts.cpp | 2 +- .../Browser/Bridge/Base/AddModel.cpp | 4 +- .../Interface/Browser/Bridge/Base/AddModel.h | 2 +- .../Browser/Bridge/Base/GetDocumentState.cpp | 2 +- .../Browser/Bridge/Base/RemoveModel.cpp | 4 +- .../Browser/Bridge/Base/RemoveModel.h | 2 +- .../Browser/Bridge/Base/UpdateModel.cpp | 4 +- .../Browser/Bridge/Base/UpdateModel.h | 2 +- .../Browser/Bridge/Config/UpdateConfig.cpp | 2 +- .../Browser/Bridge/Send/GetSendFilters.cpp | 8 +- .../Browser/Bridge/Test/TriggerEvent.cpp | 4 +- .../Browser/Bridge/Test/TriggerEvent.h | 2 +- .../Connector/Record/Model/CardMover.cpp | 6 +- .../Connector/Record/Model/CardMover.h | 2 +- .../Connector/Record/Model/CardSetting.cpp | 3 +- .../Model/Filter/ArchicadEverythingFilter.h | 38 ++++++ .../Model/Filter/ArchicadSelectionFilter.h | 38 ++++++ .../Filter/DirectSelectionSendFilter.cpp | 31 ++--- .../Model/Filter/DirectSelectionSendFilter.h | 47 ++----- .../Model/Filter/EverythingSendFilter.cpp | 71 +++++++++++ .../Model/Filter/EverythingSendFilter.h | 73 +++++++++++ .../Record/Model/Filter/FilterMover.cpp | 12 +- .../Record/Model/Filter/FilterMover.h | 2 +- .../Record/Model/Filter/SendFilter.cpp | 18 +++ .../Record/Model/Filter/SendFilter.h | 44 ++++--- .../Connector/Record/Model/ModelCard.cpp | 2 +- .../Connector/Record/Model/ModelCard.h | 6 +- .../Record/Model/ReceiverModelCard.cpp | 102 +++++++++++++++ .../Record/Model/ReceiverModelCard.h | 116 ++++++++++++++++++ .../Record/Model/SenderModelCard.cpp | 1 - .../Speckle/Database/Identity/RecordID.h | 6 + .../DocumentStore/DocumentStoreEngine.h | 1 - .../Bridge/Functions/GetCallResult.cpp | 4 +- .../Browser/Bridge/Functions/GetCallResult.h | 2 +- .../Speckle/Interface/Browser/NamedFunction.h | 4 +- 37 files changed, 601 insertions(+), 108 deletions(-) create mode 100644 SpeckleConnector/Connector/Database/Identity/RecordID.h create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/ArchicadEverythingFilter.h create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/ArchicadSelectionFilter.h create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp create mode 100644 SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h create mode 100644 SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp create mode 100644 SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index 273a6d9..11398cd 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 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 */; }; + 215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08362C95808B00CD343B /* ReceiverModelCard.cpp */; }; + 215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08452C9633A800CD343B /* EverythingSendFilter.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 */; }; @@ -288,6 +290,13 @@ 215F08292C947F4400CD343B /* CardMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardMover.h; sourceTree = ""; }; 215F082C2C94C5C000CD343B /* FilterMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilterMover.cpp; sourceTree = ""; }; 215F082D2C94C5C000CD343B /* FilterMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterMover.h; sourceTree = ""; }; + 215F08332C95808B00CD343B /* ReceiverModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReceiverModelCard.h; sourceTree = ""; }; + 215F08362C95808B00CD343B /* ReceiverModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReceiverModelCard.cpp; sourceTree = ""; }; + 215F083D2C96270100CD343B /* RecordID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordID.h; sourceTree = ""; }; + 215F08412C962F5E00CD343B /* ArchicadSelectionFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadSelectionFilter.h; sourceTree = ""; }; + 215F08442C9633A800CD343B /* EverythingSendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EverythingSendFilter.h; sourceTree = ""; }; + 215F08452C9633A800CD343B /* EverythingSendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EverythingSendFilter.cpp; sourceTree = ""; }; + 215F084A2C9782F100CD343B /* ArchicadEverythingFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ArchicadEverythingFilter.h; sourceTree = ""; }; 2161FD902BF2600C006D9527 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 219388682C4E5DE2002A0180 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -912,6 +921,14 @@ name = Frameworks; sourceTree = ""; }; + 215F083E2C96270100CD343B /* Identity */ = { + isa = PBXGroup; + children = ( + 215F083D2C96270100CD343B /* RecordID.h */, + ); + path = Identity; + sourceTree = ""; + }; 219F30412C769282009834E9 /* ConnectorTests */ = { isa = PBXGroup; children = ( @@ -951,6 +968,7 @@ 21B67CCB2C77670400FD64FC /* Database */ = { isa = PBXGroup; children = ( + 215F083E2C96270100CD343B /* Identity */, 21B67CC72C77670400FD64FC /* ModelCardDatabase.cpp */, 21B67CC82C77670400FD64FC /* ModelCardDatabase.h */, ); @@ -1033,6 +1051,8 @@ 21D0BDDF2C9393980077E104 /* Filter */, 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */, 21D0BDA42C8F33AC0077E104 /* ModelCard.h */, + 215F08362C95808B00CD343B /* ReceiverModelCard.cpp */, + 215F08332C95808B00CD343B /* ReceiverModelCard.h */, 21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */, 21D0BDDB2C93897B0077E104 /* SenderModelCard.h */, ); @@ -1042,8 +1062,12 @@ 21D0BDDF2C9393980077E104 /* Filter */ = { isa = PBXGroup; children = ( + 215F084A2C9782F100CD343B /* ArchicadEverythingFilter.h */, + 215F08412C962F5E00CD343B /* ArchicadSelectionFilter.h */, 21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */, 21D0BDE22C943C630077E104 /* DirectSelectionSendFilter.h */, + 215F08452C9633A800CD343B /* EverythingSendFilter.cpp */, + 215F08442C9633A800CD343B /* EverythingSendFilter.h */, 215F082C2C94C5C000CD343B /* FilterMover.cpp */, 215F082D2C94C5C000CD343B /* FilterMover.h */, 21D0BDDD2C9393980077E104 /* SendFilter.cpp */, @@ -1371,6 +1395,7 @@ files = ( 21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */, 21B67CE32C78D1FB00FD64FC /* SayHiArg.cpp in Sources */, + 215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */, 21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */, 21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */, 21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */, @@ -1395,6 +1420,7 @@ 21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */, 21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */, 215F082A2C947F4400CD343B /* CardMover.cpp in Sources */, + 215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */, 21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */, 21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */, 215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */, diff --git a/SpeckleConnector/Connector/Database/Identity/RecordID.h b/SpeckleConnector/Connector/Database/Identity/RecordID.h new file mode 100644 index 0000000..ad36268 --- /dev/null +++ b/SpeckleConnector/Connector/Database/Identity/RecordID.h @@ -0,0 +1,16 @@ +#ifndef CONNECTOR_DATABASE_ID +#define CONNECTOR_DATABASE_ID + +#include "Speckle/Utility/Guid.h" + +namespace connector::database { + + //BIM element record identifier + using ElementID = speckle::utility::Guid; + + //A list of element IDs + using ElementIDList = std::vector; + +} + +#endif //CONNECTOR_DATABASE_ID diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Account/GetAccounts.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Account/GetAccounts.cpp index b32c6a4..ecf0f99 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Account/GetAccounts.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Account/GetAccounts.cpp @@ -14,7 +14,7 @@ using namespace speckle::utility; namespace { - using WrappedValue = active::serialise::CargoHold, Vector>; + using WrappedValue = active::serialise::CargoHold>, Vector>; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp index daa5299..6c08025 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp @@ -19,7 +19,7 @@ namespace { /*-------------------------------------------------------------------- Default constructor --------------------------------------------------------------------*/ -AddModel::AddModel() : BridgeMethod{"AddModel", [&](ModelCardEventWrapper card) { +AddModel::AddModel() : BridgeMethod{"AddModel", [&](const ModelCardEventWrapper& card) { return run(card.get()); }} {} @@ -29,7 +29,7 @@ AddModel::AddModel() : BridgeMethod{"AddModel", [&](ModelCardEventWrapper card) card: The card to add --------------------------------------------------------------------*/ -void AddModel::run(ModelCard& card) const { +void AddModel::run(const ModelCard& card) const { if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) modelCardDBase->write(card); } //AddModel::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h index 4573486..bca8410 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.h @@ -32,7 +32,7 @@ namespace connector::interfac::browser::bridge { Add a model card to document storage @param card The card to add */ - void run(connector::record::ModelCard& card) const; + void run(const connector::record::ModelCard& card) const; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp index b0ecc18..04d0f6c 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/GetDocumentState.cpp @@ -15,7 +15,7 @@ using namespace speckle::utility; namespace { - using WrappedValue = active::serialise::CargoHold, Vector>; + using WrappedValue = active::serialise::CargoHold>, Vector>; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp index d6dd2f4..722d2fa 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.cpp @@ -20,7 +20,7 @@ namespace { /*-------------------------------------------------------------------- Default constructor --------------------------------------------------------------------*/ -RemoveModel::RemoveModel() : BridgeMethod{"RemoveModel", [&](ModelCardEventWrapper card) { +RemoveModel::RemoveModel() : BridgeMethod{"RemoveModel", [&](const ModelCardEventWrapper& card) { return run(card.get()); }} {} @@ -30,7 +30,7 @@ RemoveModel::RemoveModel() : BridgeMethod{"RemoveModel", [&](ModelCardEventWrapp card: The card to add --------------------------------------------------------------------*/ -void RemoveModel::run(ModelCard& card) const { +void RemoveModel::run(const ModelCard& card) const { if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) modelCardDBase->erase(card.getID()); } //RemoveModel::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h index dbdc99a..50c6d00 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/RemoveModel.h @@ -32,7 +32,7 @@ namespace connector::interfac::browser::bridge { Add a model card to document storage @param card The card to add */ - void run(connector::record::ModelCard& card) const; + void run(const connector::record::ModelCard& card) const; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp index 7fcd02c..cd845dc 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp @@ -20,7 +20,7 @@ namespace { /*-------------------------------------------------------------------- Default constructor --------------------------------------------------------------------*/ -UpdateModel::UpdateModel() : BridgeMethod{"UpdateModel", [&](ModelCardEventWrapper card) { +UpdateModel::UpdateModel() : BridgeMethod{"UpdateModel", [&](const ModelCardEventWrapper& card) { return run(card.get()); }} {} @@ -30,7 +30,7 @@ UpdateModel::UpdateModel() : BridgeMethod{"UpdateModel", [&](ModelCardEventWrapp card: The card to add --------------------------------------------------------------------*/ -void UpdateModel::run(ModelCard& card) const { +void UpdateModel::run(const ModelCard& card) const { if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) modelCardDBase->write(card); } //UpdateModel::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h index cbca60a..e4263fe 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.h @@ -32,7 +32,7 @@ namespace connector::interfac::browser::bridge { Add a model card to document storage @param card The card to add */ - void run(connector::record::ModelCard& card) const; + void run(const connector::record::ModelCard& card) const; }; } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Config/UpdateConfig.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Config/UpdateConfig.cpp index 1977dc6..515f127 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Config/UpdateConfig.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Config/UpdateConfig.cpp @@ -10,7 +10,7 @@ using namespace speckle::utility; /*-------------------------------------------------------------------- Default constructor --------------------------------------------------------------------*/ -UpdateConfig::UpdateConfig() : BridgeMethod{"UpdateConfig", [&](UpdateArgs args) { +UpdateConfig::UpdateConfig() : BridgeMethod{"UpdateConfig", [&](const UpdateArgs& args) { run(args); }} {} diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp index 4f16d00..9829303 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp @@ -4,7 +4,8 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/ContainerWrap.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" -#include "Connector/Record/Model/Filter/SendFilter.h" +#include "Connector/Record/Model/Filter/ArchicadEverythingFilter.h" +#include "Connector/Record/Model/Filter/ArchicadSelectionFilter.h" using namespace active::container; using namespace active::serialise; @@ -14,7 +15,7 @@ using namespace speckle::utility; namespace { - using WrappedValue = active::serialise::CargoHold, Vector>; + using WrappedValue = active::serialise::CargoHold>, Vector>; } @@ -33,6 +34,7 @@ GetSendFilters::GetSendFilters() : BridgeMethod{"GetSendFilters", [&]() { --------------------------------------------------------------------*/ std::unique_ptr GetSendFilters::run() const { Vector filters; - ///TODO: Get real filters + filters.emplace_back(ArchicadEverythingFilter{}); + filters.emplace_back(ArchicadSelectionFilter{}); return std::make_unique(filters); } //GetSendFilters::run diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.cpp index 1981c3f..a6dd5bf 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.cpp @@ -85,7 +85,7 @@ namespace { /*-------------------------------------------------------------------- Default constructor --------------------------------------------------------------------*/ -TriggerEvent::TriggerEvent() : BridgeMethod{"TriggerEvent", [&](TriggerEventWrapper arg) { +TriggerEvent::TriggerEvent() : BridgeMethod{"TriggerEvent", [&](const TriggerEventWrapper& arg) { return run(arg); }} {} @@ -95,7 +95,7 @@ TriggerEvent::TriggerEvent() : BridgeMethod{"TriggerEvent", [&](TriggerEventWrap eventName: The event name --------------------------------------------------------------------*/ -void TriggerEvent::run(speckle::utility::String eventName) const { +void TriggerEvent::run(const speckle::utility::String& eventName) const { if (!hasBridge()) return; if (eventName == "emptyTestEvent") diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.h index 323087a..a38c80a 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Test/TriggerEvent.h @@ -31,7 +31,7 @@ namespace connector::interfac::browser::bridge { Trigger an event based on a specified name @param eventName The event name */ - void run(speckle::utility::String eventName) const; + void run(const speckle::utility::String& eventName) const; }; } diff --git a/SpeckleConnector/Connector/Record/Model/CardMover.cpp b/SpeckleConnector/Connector/Record/Model/CardMover.cpp index 841e05b..f2c1a60 100644 --- a/SpeckleConnector/Connector/Record/Model/CardMover.cpp +++ b/SpeckleConnector/Connector/Record/Model/CardMover.cpp @@ -5,6 +5,7 @@ Distributed under the MIT License (See accompanying file LICENSE.txt or copy at #include "Connector/Record/Model/CardMover.h" +#include "Connector/Record/Model/ReceiverModelCard.h" #include "Connector/Record/Model/SenderModelCard.h" using namespace active::serialise; @@ -15,10 +16,10 @@ 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"; + ///Identity for a SenderModelCard + const char* senderCardTypeName = "SenderModelCard"; } @@ -52,5 +53,6 @@ CardMover::CardMover(const active::serialise::Package& outgoing) : Mover{outgoin void CardMover::validateHandler() { if (!m_handler->empty()) return; + m_handler->add(receiverCardTypeName); m_handler->add(senderCardTypeName); } //CardMover::validateHandler diff --git a/SpeckleConnector/Connector/Record/Model/CardMover.h b/SpeckleConnector/Connector/Record/Model/CardMover.h index 09ec860..7e3fa0f 100644 --- a/SpeckleConnector/Connector/Record/Model/CardMover.h +++ b/SpeckleConnector/Connector/Record/Model/CardMover.h @@ -6,7 +6,7 @@ namespace connector::record { /*! - Wrapper to box/unbox objects during (de)serialisation, reading/writing a specified attribute to determine object type + Wrapper to box/unbox objects during (de)serialisation, including 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 diff --git a/SpeckleConnector/Connector/Record/Model/CardSetting.cpp b/SpeckleConnector/Connector/Record/Model/CardSetting.cpp index ecd1fc1..abfb10a 100644 --- a/SpeckleConnector/Connector/Record/Model/CardSetting.cpp +++ b/SpeckleConnector/Connector/Record/Model/CardSetting.cpp @@ -2,6 +2,7 @@ #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Active/Serialise/Item/Wrapper/AnyValueWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" #include @@ -74,7 +75,7 @@ Cargo::Unique CardSetting::getCargo(const Inventory::Item& item) const { case valueID: return std::make_unique(*m_value); case enumID: - return std::make_unique>(m_type); + return std::make_unique>>(m_enum); default: return nullptr; //Requested an unknown index } diff --git a/SpeckleConnector/Connector/Record/Model/Filter/ArchicadEverythingFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/ArchicadEverythingFilter.h new file mode 100644 index 0000000..19f2af6 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/ArchicadEverythingFilter.h @@ -0,0 +1,38 @@ +#ifndef CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER +#define CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER + +#include "Connector/Database/Identity/RecordID.h" +#include "Connector/Record/Model/Filter/EverythingSendFilter.h" + +namespace connector::record { + + /*! + A send filter consisting of a list of selected Archicad element IDs + */ + class ArchicadEverythingFilter : public EverythingSendFilter { + public: + + // MARK: - Types + + using base = EverythingSendFilter; + + // MARK: - Constructors + + /*! + Default constructor + @param sum A summary + @param isDef True if this is the default filter + */ + ArchicadEverythingFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{sum, isDef} {} + /*! + Record cloning + @return A clone of this record + */ + ArchicadEverythingFilter* clonePtr() const override { return new ArchicadEverythingFilter(*this); }; + + // MARK: - Functions (const) + }; + +} + +#endif //CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER diff --git a/SpeckleConnector/Connector/Record/Model/Filter/ArchicadSelectionFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/ArchicadSelectionFilter.h new file mode 100644 index 0000000..231e3b4 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/ArchicadSelectionFilter.h @@ -0,0 +1,38 @@ +#ifndef CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER +#define CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER + +#include "Connector/Database/Identity/RecordID.h" +#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h" + +namespace connector::record { + + /*! + A send filter consisting of a list of selected Archicad element IDs + */ + class ArchicadSelectionFilter : public DirectSelectionSendFilter { + public: + + // MARK: - Types + + using base = DirectSelectionSendFilter; + + // MARK: - Constructors + + /*! + Default constructor + @param sum A summary + @param isDef True if this is the default filter + */ + ArchicadSelectionFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{sum, isDef} {} + /*! + Record cloning + @return A clone of this record + */ + ArchicadSelectionFilter* clonePtr() const override { return new ArchicadSelectionFilter(*this); }; + + // MARK: - Functions (const) + }; + +} + +#endif //CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER diff --git a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp index 25563fd..4463b06 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp +++ b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp @@ -1,10 +1,13 @@ #include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include #include using namespace active::serialise; +using namespace connector::database; using namespace connector::record; using namespace speckle::utility; @@ -12,16 +15,12 @@ namespace { ///Serialisation fields enum FieldIndex { - nameID, - summaryID, - defaultID, + selectedElemID, }; ///Serialisation field IDs static std::array fieldID = { - Identity{"name"}, - Identity{"summary"}, - Identity{"isDefault"}, + Identity{"selectedObjectIds"}, }; } @@ -37,12 +36,10 @@ bool DirectSelectionSendFilter::fillInventory(Inventory& inventory) const { using enum Entry::Type; inventory.merge(Inventory{ { - { fieldID[nameID], nameID, element }, - { fieldID[summaryID], summaryID, element }, - { fieldID[defaultID], defaultID, element }, + { fieldID[selectedElemID], selectedElemID, element }, }, }.withType(&typeid(DirectSelectionSendFilter))); - return true; + return base::fillInventory(inventory); } //DirectSelectionSendFilter::fillInventory @@ -55,15 +52,11 @@ bool DirectSelectionSendFilter::fillInventory(Inventory& inventory) const { --------------------------------------------------------------------*/ Cargo::Unique DirectSelectionSendFilter::getCargo(const Inventory::Item& item) const { if (item.ownerType != &typeid(DirectSelectionSendFilter)) - return nullptr; + return base::getCargo(item); using namespace active::serialise; switch (item.index) { - case nameID: - return std::make_unique>(m_name); - case summaryID: - return std::make_unique>(m_summary); - case defaultID: - return std::make_unique>(m_isDefault); + case selectedElemID: + return std::make_unique>(m_selectedElements); default: return nullptr; //Requested an unknown index } @@ -74,7 +67,5 @@ Cargo::Unique DirectSelectionSendFilter::getCargo(const Inventory::Item& item) c Set to the default package content --------------------------------------------------------------------*/ void DirectSelectionSendFilter::setDefault() { - m_name.clear(); - m_summary.clear(); - m_isDefault = false; + m_selectedElements.clear(); } //DirectSelectionSendFilter::setDefault diff --git a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h index 18e8d0d..b4ae701 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h +++ b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h @@ -1,59 +1,42 @@ #ifndef CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER #define CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER -#include "Active/Serialise/Package/Package.h" -#include "Active/Utility/Cloner.h" -#include "Speckle/Utility/String.h" +#include "Connector/Database/Identity/RecordID.h" +#include "Connector/Record/Model/Filter/SendFilter.h" namespace connector::record { /*! - Base class for element filters applied when a model is sent to a Speckle server + A send filter consisting of a list of selected element IDs */ - class DirectSelectionSendFilter : public active::serialise::Package, public active::utility::Cloner { + class DirectSelectionSendFilter : public SendFilter { public: // MARK: - Types - using base = active::serialise::Package; + using base = SendFilter; // MARK: - Constructors /*! Default constructor - @param nm The filter name @param sum A summary @param isDef True if this is the default filter */ - DirectSelectionSendFilter(const speckle::utility::String& nm = {}, const speckle::utility::String& sum = {}, bool isDef = false) : - m_name{nm}, m_summary{sum}, m_isDefault{isDef} {} - /*! - Destructor - */ - virtual ~DirectSelectionSendFilter() {} + DirectSelectionSendFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{"Selection", sum, isDef} {} /*! Record cloning @return A clone of this record */ - virtual DirectSelectionSendFilter* clonePtr() const override { return new DirectSelectionSendFilter(*this); }; + DirectSelectionSendFilter* clonePtr() const override { return new DirectSelectionSendFilter(*this); }; // MARK: - Functions (const) /*! - Get the filter name - @return The filter name - */ - const speckle::utility::String& getName() const { return m_name; }; - /*! - Get a summary description of the filter function, e.g. "All selected elements" - @return The filter summary description - */ - const speckle::utility::String& getSummary() const { return m_name; }; - /*! - Determine if this is the default filter for model sends - @return True if this is the default filter - */ - bool isDefault() const { return m_isDefault; }; + Get the filtered element IDs + @return The filter elements + */ + const database::ElementIDList& getElementIDs() const override { return m_selectedElements; } // MARK: - Serialisation @@ -75,12 +58,8 @@ namespace connector::record { void setDefault() override; private: - ///The filter name - speckle::utility::String m_name; - ///A summary - speckle::utility::String m_summary; - ///True if this is the default filter - bool m_isDefault = false; + ///A list of selected element IDs + database::ElementIDList m_selectedElements; }; } diff --git a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp new file mode 100644 index 0000000..791bc41 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp @@ -0,0 +1,71 @@ +#include "Connector/Record/Model/Filter/EverythingSendFilter.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" + +#include +#include + +using namespace active::serialise; +using namespace connector::database; +using namespace connector::record; +using namespace speckle::utility; + +namespace { + + ///Serialisation fields + enum FieldIndex { + selectedElemID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"selectedObjectIds"}, + }; + +} + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool EverythingSendFilter::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[selectedElemID], selectedElemID, element }, + }, + }.withType(&typeid(EverythingSendFilter))); + return base::fillInventory(inventory); +} //EverythingSendFilter::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique EverythingSendFilter::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(EverythingSendFilter)) + return base::getCargo(item); + using namespace active::serialise; + switch (item.index) { + case selectedElemID: + return std::make_unique>(m_emptyList); + default: + return nullptr; //Requested an unknown index + } +} //EverythingSendFilter::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void EverythingSendFilter::setDefault() { + m_emptyList.clear(); +} //EverythingSendFilter::setDefault diff --git a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h new file mode 100644 index 0000000..94e2303 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h @@ -0,0 +1,73 @@ +#ifndef CONNECTOR_RECORD_EVERYTHING_SEND_FILTER +#define CONNECTOR_RECORD_EVERYTHING_SEND_FILTER + +#include "Connector/Database/Identity/RecordID.h" +#include "Connector/Record/Model/Filter/SendFilter.h" + +namespace connector::record { + + /*! + A send filter consisting of a list of selected element IDs + */ + class EverythingSendFilter : public SendFilter { + public: + + // MARK: - Types + + using base = SendFilter; + + // MARK: - Constructors + + /*! + Default constructor + @param sum A summary + @param isDef True if this is the default filter + */ + EverythingSendFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{"Everything", sum, isDef} {} + /*! + Record cloning + @return A clone of this record + */ + EverythingSendFilter* clonePtr() const override { return new EverythingSendFilter(*this); }; + + // MARK: - Functions (const) + + /*! + Get the filtered element IDs + @return The filter elements + */ + const database::ElementIDList& getElementIDs() const override { return m_emptyList; } + /*! + Determine if the filter has expired because an element in the selection has changed + @param changed The list of changed element IDs + @return True if the one of the changed elements is in the selection + */ + virtual bool checkExpiry(const database::ElementIDList& changed) const override { return true; } + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + ///Enables a const empty list to be returned + database::ElementIDList m_emptyList; + }; + +} + +#endif //CONNECTOR_RECORD_EVERYTHING_SEND_FILTER diff --git a/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp index 5712d2d..a4f5c32 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp +++ b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.cpp @@ -5,7 +5,8 @@ Distributed under the MIT License (See accompanying file LICENSE.txt or copy at #include "Connector/Record/Model/Filter/FilterMover.h" -#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h" +#include "Connector/Record/Model/Filter/ArchicadEverythingFilter.h" +#include "Connector/Record/Model/Filter/ArchicadSelectionFilter.h" using namespace active::serialise; using namespace active::utility; @@ -16,8 +17,10 @@ namespace { ///The tag used to identify a Speckle type name value const char* attributeTag = "typeDiscriminator"; ///Identity for a SenderModelCard - const char* DirectSelectionTypeName = "DirectSelectionSendFilter"; - + const char* ArchicadSelectionTypeName = "ArchicadSelectionFilter"; + ///Identity for a SenderModelCard + const char* ArchicadEverythingTypeName = "ArchicadEverythingFilter"; + } ///The handler for model card packages @@ -60,5 +63,6 @@ FilterMover::FilterMover(active::serialise::PackageUniqueWrap&& package) : Mover void FilterMover::validateHandler() { if (!m_handler->empty()) return; - m_handler->add(DirectSelectionTypeName); + m_handler->add(ArchicadEverythingTypeName); + m_handler->add(ArchicadSelectionTypeName); } //FilterMover::validateHandler diff --git a/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h index 48e13a1..dc326a1 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h +++ b/SpeckleConnector/Connector/Record/Model/Filter/FilterMover.h @@ -6,7 +6,7 @@ namespace connector::record { /*! - Wrapper to box/unbox objects during (de)serialisation, reading/writing a specified attribute to determine object type + Wrapper to box/unbox objects during (de)serialisation, including 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 diff --git a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp index 08a17e8..c624d96 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp +++ b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp @@ -5,6 +5,7 @@ #include using namespace active::serialise; +using namespace connector::database; using namespace connector::record; using namespace speckle::utility; @@ -26,6 +27,23 @@ namespace { } +/*-------------------------------------------------------------------- + Determine if the filter has expired because an element in the selection has changed + + changed: The list of changed element IDs + + return: True if the one of the changed elements is in the selection + --------------------------------------------------------------------*/ +bool SendFilter::checkExpiry(const ElementIDList& changed) const { + ElementIDList intersect; + ElementIDList mine{getElementIDs()}, theirs{changed}; + std::sort(mine.begin(), mine.end()); + std::sort(theirs.begin(), theirs.end()); + std::set_intersection (mine.begin(), mine.end(), theirs.begin(), theirs.end(), std::back_inserter(intersect)); + return !intersect.empty(); +} //SendFilter::checkExpiry + + /*-------------------------------------------------------------------- Fill an inventory with the package items diff --git a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h index fc0e0dd..999d5fd 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h +++ b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h @@ -3,6 +3,7 @@ #include "Active/Serialise/Package/Package.h" #include "Active/Utility/Cloner.h" +#include "Connector/Database/Identity/RecordID.h" #include "Speckle/Utility/String.h" namespace connector::record { @@ -32,45 +33,56 @@ namespace connector::record { */ virtual ~SendFilter() {} /*! - Record cloning - @return A clone of this record + Object cloning + @return A clone of this object */ - virtual SendFilter* clonePtr() const override { return new SendFilter(*this); }; + virtual SendFilter* clonePtr() const override = 0; // MARK: - Functions (const) /*! - Get the filter name - @return The filter name + Get the filter name + @return The filter name */ const speckle::utility::String& getName() const { return m_name; }; /*! - Get a summary description of the filter function, e.g. "All selected elements" - @return The filter summary description + Get a summary description of the filter function, e.g. "All selected elements" + @return The filter summary description */ const speckle::utility::String& getSummary() const { return m_name; }; /*! - Determine if this is the default filter for model sends - @return True if this is the default filter + Determine if this is the default filter for model sends + @return True if this is the default filter */ bool isDefault() const { return m_isDefault; }; + /*! + Get the filtered element IDs + @return The filter elements + */ + virtual const database::ElementIDList& getElementIDs() const = 0; + /*! + Determine if the filter has expired because an element in the selection has changed + @param changed The list of changed element IDs + @return True if the one of the changed elements is in the selection + */ + virtual bool checkExpiry(const database::ElementIDList& changed) const; // MARK: - Serialisation /*! - Fill an inventory with the package items - @param inventory The inventory to receive the package items - @return True if the package has added items to the inventory + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory */ bool fillInventory(active::serialise::Inventory& inventory) const override; /*! - Get the specified cargo - @param item The inventory item to retrieve - @return The requested cargo (nullptr on failure) + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) */ Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; /*! - Set to the default package content + Set to the default package content */ void setDefault() override; diff --git a/SpeckleConnector/Connector/Record/Model/ModelCard.cpp b/SpeckleConnector/Connector/Record/Model/ModelCard.cpp index 3f7dcce..ec29cd7 100644 --- a/SpeckleConnector/Connector/Record/Model/ModelCard.cpp +++ b/SpeckleConnector/Connector/Record/Model/ModelCard.cpp @@ -75,7 +75,7 @@ Cargo::Unique ModelCard::getCargo(const Inventory::Item& item) const { case serverURLID: return std::make_unique>(m_serverURL); case settingsID: - return std::make_unique>(m_settings); + return std::make_unique>>(m_settings); default: return nullptr; //Requested an unknown index } diff --git a/SpeckleConnector/Connector/Record/Model/ModelCard.h b/SpeckleConnector/Connector/Record/Model/ModelCard.h index 6503753..f5a03fc 100644 --- a/SpeckleConnector/Connector/Record/Model/ModelCard.h +++ b/SpeckleConnector/Connector/Record/Model/ModelCard.h @@ -87,11 +87,11 @@ namespace connector::record { private: ///The model ID - speckle::utility::String m_modelID; + speckle::database::RecordID m_modelID; ///The project ID - speckle::utility::String m_projectID; + speckle::database::RecordID m_projectID; ///The user account ID - speckle::utility::String m_accountID; + speckle::database::RecordID m_accountID; ///The server URL speckle::utility::String m_serverURL; ///Settings for the model rendering, e.g. level of detail (LoD) diff --git a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp new file mode 100644 index 0000000..3877f7c --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp @@ -0,0 +1,102 @@ +#include "Connector/Record/Model/ReceiverModelCard.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" + +#include + +using namespace active::serialise; +using namespace connector::database; +using namespace connector::record; +using namespace speckle::database; +using namespace speckle::utility; + +namespace { + + ///Serialisation fields + enum FieldIndex { + projectNameID, + modelNameID, + selectedVersionID, + latestVersionID, + warningDismissedID, + bakedObjectsID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"projectName"}, + Identity{"modelName"}, + Identity{"selectedVersionID"}, + Identity{"latestVersionID"}, + Identity{"hasDismissedUpdateWarning"}, + Identity{"bakedObjectIds"}, + }; + +} + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool ReceiverModelCard::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[projectNameID], projectNameID, element }, + { fieldID[modelNameID], modelNameID, element }, + { fieldID[selectedVersionID], selectedVersionID, element }, + { fieldID[latestVersionID], latestVersionID, element }, + { fieldID[warningDismissedID], warningDismissedID, element }, + { fieldID[bakedObjectsID], bakedObjectsID, element }, + }, + }.withType(&typeid(ReceiverModelCard))); + return base::fillInventory(inventory); +} //ReceiverModelCard::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique ReceiverModelCard::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(ReceiverModelCard)) + return base::getCargo(item); + using namespace active::serialise; + switch (item.index) { + case projectNameID: + return std::make_unique(m_projectName); + case modelNameID: + return std::make_unique(m_modelName); + case selectedVersionID: + return std::make_unique>(m_selectedVersionID); + case latestVersionID: + return std::make_unique>(m_latestVersionID); + case warningDismissedID: + return std::make_unique(m_hasDismissedUpdateWarning); + case bakedObjectsID: + return std::make_unique>(m_bakedObjectIDs); + default: + return nullptr; //Requested an unknown index + } +} //ReceiverModelCard::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void ReceiverModelCard::setDefault() { + base::setDefault(); + m_projectName.clear(); + m_modelName.clear(); + m_selectedVersionID.clear(); + m_latestVersionID.clear(); + m_hasDismissedUpdateWarning = false; + m_bakedObjectIDs.clear(); +} //ReceiverModelCard::setDefault diff --git a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h new file mode 100644 index 0000000..6357679 --- /dev/null +++ b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h @@ -0,0 +1,116 @@ +#ifndef CONNECTOR_RECORD_RECEIVER_MODEL_CARD +#define CONNECTOR_RECORD_RECEIVER_MODEL_CARD + +#include "Connector/Database/Identity/RecordID.h" +#include "Connector/Record/Model/ModelCard.h" + +namespace connector::record { + + class SendFilter; + + /*! + A connector model send card - carries information about what was sent with the model + */ + class ReceiverModelCard : public connector::record::ModelCard { + public: + + // MARK: - Types + + using base = connector::record::ModelCard; + + // MARK: - Constructors + + /*! + Default constructor + */ + ReceiverModelCard() {} + /*! + Constructor + @param projectName The project name + @param modelName The model name + @param selectedVersion The selected version ID + @param latestVersion The latest version ID + @param hasDimissedWarning True if the user has already dismissed an alert to update + @param bakedObjects The IDs of objects accepted in the receive + */ + ReceiverModelCard(const speckle::utility::String& projectName, const speckle::utility::String& modelName, + const speckle::database::RecordID& selectedVersion, const speckle::database::RecordID& latestVersion, + bool hasDimissedWarning, database::ElementIDList&& bakedObjects) : + m_projectName{projectName}, m_modelName{modelName}, m_selectedVersionID{selectedVersion}, m_latestVersionID{latestVersion}, + m_hasDismissedUpdateWarning{hasDimissedWarning}, m_bakedObjectIDs{bakedObjects} {} + /*! + Record cloning + @return A clone of this record + */ + virtual ReceiverModelCard* clonePtr() const override { return new ReceiverModelCard(*this); }; + + // MARK: - Functions (const) + + /*! + Get the project name + @return The project name + */ + const speckle::utility::String& getProjectName() const { return m_projectName; } + /*! + Get the model name + @return The model name + */ + const speckle::utility::String& getModelName() const { return m_modelName; } + /*! + Get the selected version ID + @return The selected version ID + */ + const speckle::database::RecordID& getSelectedVersionID() const { return m_selectedVersionID; } + /*! + Get the latest version ID + @return The latest version ID + */ + const speckle::database::RecordID& getLatestVersionID() const { return m_latestVersionID; } + /*! + Determine if the user has already dismissed an alert to update + @return True if the user has already dismissed an alert to update + */ + bool hasDismissedUpdateWarning() const { return m_hasDismissedUpdateWarning; } + /*! + Get the IDs of objects accepted in the receive + @return The accepted object IDs + */ + const database::ElementIDList& getBakedObjectIDs() const { return m_bakedObjectIDs; } + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + ///The received project name + speckle::utility::String m_projectName; + ///The received model name + speckle::utility::String m_modelName; + ///The ID of the version selected in the receive + speckle::database::RecordID m_selectedVersionID; + ///The ID of the latest version + speckle::database::RecordID m_latestVersionID; + ///True if the user has already dismissed an alert to update + bool m_hasDismissedUpdateWarning = false; + ///IDs of objects accepted in the receive + database::ElementIDList m_bakedObjectIDs; + }; + +} + +#endif //CONNECTOR_RECORD_RECEIVER_MODEL_CARD diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp index 08e1d8b..af8e31c 100644 --- a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp +++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp @@ -1,6 +1,5 @@ #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" diff --git a/SpeckleLib/Speckle/Database/Identity/RecordID.h b/SpeckleLib/Speckle/Database/Identity/RecordID.h index 1a8267f..b26eadd 100644 --- a/SpeckleLib/Speckle/Database/Identity/RecordID.h +++ b/SpeckleLib/Speckle/Database/Identity/RecordID.h @@ -5,10 +5,16 @@ namespace speckle::database { + //Common Speckle record identifier type using RecordID = speckle::utility::String; + //Common Speckle table identifier type using TableID = speckle::utility::String; + //Common Speckle database identifier type using DBaseID = speckle::utility::String; + //A list of record IDs + using RecordIDList = std::vector; + } #endif //SPECKLE_DATABASE_ID diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index 9ec72f7..015975c 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -6,7 +6,6 @@ #include "Active/Database/Storage/RecordCache.h" #include "Active/File/Path.h" #include "Active/Serialise/Cargo.h" -#include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" #include "Active/Serialise/Transport.h" #include "Active/Utility/BufferIn.h" diff --git a/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.cpp b/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.cpp index 464e9b2..bd1b319 100644 --- a/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.cpp +++ b/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.cpp @@ -21,7 +21,7 @@ using namespace speckle::utility; /*-------------------------------------------------------------------- Constructor --------------------------------------------------------------------*/ -GetCallResult::GetCallResult() : JSFunction{"GetCallResult", [&](auto args) { +GetCallResult::GetCallResult() : JSFunction{"GetCallResult", [&](const auto& args) { return getResult(args); }} { } //GetCallResult::GetCallResult @@ -34,7 +34,7 @@ GetCallResult::GetCallResult() : JSFunction{"GetCallResult", [&](auto args) { return: The requested result (nullptr on failure) --------------------------------------------------------------------*/ -std::unique_ptr GetCallResult::getResult(WrappedResultArg& argument) const { +std::unique_ptr GetCallResult::getResult(const WrappedResultArg& argument) const { if (!hasBridge()) return nullptr; //Retrieve the requested result diff --git a/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.h b/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.h index 562eab2..61a9146 100644 --- a/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.h +++ b/SpeckleLib/Speckle/Interface/Browser/Bridge/Functions/GetCallResult.h @@ -34,7 +34,7 @@ namespace speckle::interfac::browser::bridge { @param argument The method arguments specifying the target bridge and requestID @return The requested result (nullptr on failure) */ - std::unique_ptr getResult(WrappedResultArg& argument) const; + std::unique_ptr getResult(const WrappedResultArg& argument) const; }; } diff --git a/SpeckleLib/Speckle/Interface/Browser/NamedFunction.h b/SpeckleLib/Speckle/Interface/Browser/NamedFunction.h index 8f05475..2c574f6 100644 --- a/SpeckleLib/Speckle/Interface/Browser/NamedFunction.h +++ b/SpeckleLib/Speckle/Interface/Browser/NamedFunction.h @@ -20,7 +20,7 @@ namespace speckle::interfac::browser { struct FuncBase {}; template struct FuncTypedef { - typedef std::function(Argument)> type; + typedef std::function(const Argument&)> type; }; template struct FuncTypedef { @@ -28,7 +28,7 @@ namespace speckle::interfac::browser { }; template struct FuncTypedef { - typedef std::function type; + typedef std::function type; }; template<> struct FuncTypedef { From 8ea4ced15324fc7b6a3786bdd2d93cbef6574411 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Mon, 16 Sep 2024 08:54:18 +0100 Subject: [PATCH 12/16] Updated VS projects --- SpeckleConnector/Connector.vcxproj | 37 ++++-- SpeckleConnector/Connector.vcxproj.filters | 118 ++++++++++++++---- .../Model/Filter/EverythingSendFilter.cpp | 2 + SpeckleLib/Speckle/Utility/Guid.h | 11 ++ 4 files changed, 134 insertions(+), 34 deletions(-) diff --git a/SpeckleConnector/Connector.vcxproj b/SpeckleConnector/Connector.vcxproj index 5c34307..ce15579 100644 --- a/SpeckleConnector/Connector.vcxproj +++ b/SpeckleConnector/Connector.vcxproj @@ -93,11 +93,10 @@ - - - + + @@ -105,12 +104,13 @@ + + - @@ -122,16 +122,25 @@ + + + + + + + + + - - - + + + @@ -139,12 +148,13 @@ + + - @@ -156,6 +166,17 @@ + + + + + + + + + + + diff --git a/SpeckleConnector/Connector.vcxproj.filters b/SpeckleConnector/Connector.vcxproj.filters index d63175d..8eb6949 100644 --- a/SpeckleConnector/Connector.vcxproj.filters +++ b/SpeckleConnector/Connector.vcxproj.filters @@ -32,12 +32,6 @@ {2f459f56-86f0-4794-b4b7-1bd7b8ee5617} - - {2820ad4f-60d9-436e-a7a2-d019d7e0ce0c} - - - {85935d00-16ac-466a-a614-ad9ea802bffa} - {6a2f1f18-a554-4546-bba3-314d5f2ec9f9} @@ -53,8 +47,17 @@ {2b87cf11-87cd-435f-ab24-42170c2e657e} - - {3bc97363-0091-4f84-a5f7-085193bad850} + + {41395ee2-50f3-49c0-8859-23a3ad19a2fa} + + + {a915e7ee-849f-48a9-aa7b-0ef6e358bee7} + + + {2b16c188-1d80-4d4d-830e-5c1e56ecf46e} + + + {b6d6326c-77f4-414a-bda6-e3e587c7ded2} @@ -122,9 +125,6 @@ Connector\Interface\Browser\Bridge\Base - - Connector\Database\Model\Card - Connector\Interface\Browser\Bridge\Config\Arg @@ -159,14 +159,44 @@ Connector\Interface\Browser\Bridge\Send - - Connector\Interface\Browser\Bridge\Send\Arg + + Connector\Database - - Connector\Database\Model\Card + + Connector\Record\Model - - Connector\Database\Model\Card + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Interface\Browser\Bridge\Base + + + Connector\Interface\Browser\Bridge\Base + + + Connector\Interface\Browser\Bridge\Base @@ -221,9 +251,6 @@ Connector - - Connector\Database\Model\Card - Connector\Interface\Browser\Bridge\Config\Arg @@ -258,14 +285,53 @@ Connector\Interface\Browser\Bridge\Send - - Connector\Interface\Browser\Bridge\Send\Arg + + Connector\Database - - Connector\Database\Model\Card + + Connector\Database\Identity - - Connector\Database\Model\Card + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Record\Model\Filter + + + Connector\Interface\Browser\Bridge\Base + + + Connector\Interface\Browser\Bridge\Base + + + Connector\Interface\Browser\Bridge\Base \ No newline at end of file diff --git a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp index 791bc41..9dce303 100644 --- a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp +++ b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp @@ -3,6 +3,8 @@ #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Active/Utility/Concepts.h" + #include #include diff --git a/SpeckleLib/Speckle/Utility/Guid.h b/SpeckleLib/Speckle/Utility/Guid.h index 87de071..0fcbd74 100644 --- a/SpeckleLib/Speckle/Utility/Guid.h +++ b/SpeckleLib/Speckle/Utility/Guid.h @@ -2,6 +2,7 @@ #define SPECKLE_UTILITY_GUID #include "Active/Utility/Guid.h" +#include "Speckle/Utility/String.h" #ifdef ARCHICAD #include @@ -46,6 +47,16 @@ namespace speckle::utility { using base::operator=; + /*! + Conversion operator + @return The guid as a string + */ + operator active::utility::String() const { return base::string(); } + /*! + Conversion operator + @return The guid as a string + */ + operator speckle::utility::String() const { return base::string(); } #ifdef ARCHICAD /*! Conversion operator From 220c9a5a40a231e681c2a4a1ed84590ff08c14e1 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Mon, 16 Sep 2024 15:00:55 +0100 Subject: [PATCH 13/16] ModelCard record and dbase fixes --- .../Connector/Database/ModelCardDatabase.cpp | 2 +- SpeckleConnector/Connector/Record/Model/ModelCard.h | 12 ++++++++++++ SpeckleLib/Speckle/Database/Content/Record.h | 6 ++++-- .../Storage/DocumentStore/DocumentStoreCore.cpp | 4 +--- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp index d53c689..761d8fc 100644 --- a/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp +++ b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp @@ -49,7 +49,7 @@ namespace { Constructor --------------------------------------------------------------------*/ ModelCardDatabase::ModelCardDatabase() { - auto engine = std::make_shared(modelCardDBaseName, + m_engine = std::make_shared(modelCardDBaseName, //Schema DBaseSchema{active::utility::String{modelCardDBaseName}, //Tables diff --git a/SpeckleConnector/Connector/Record/Model/ModelCard.h b/SpeckleConnector/Connector/Record/Model/ModelCard.h index f5a03fc..6db4ec5 100644 --- a/SpeckleConnector/Connector/Record/Model/ModelCard.h +++ b/SpeckleConnector/Connector/Record/Model/ModelCard.h @@ -28,6 +28,18 @@ namespace connector::record { Default constructor */ ModelCard() {} + /*! + Constructor + @param modelID The model ID + @param projectID The project ID + @param accountID The account ID + @param serverURL The server URL + @param settings Any BIM host-related settings relevant to the appearance/rendering of the model, e.g. LoD, if properties included etc + */ + ModelCard(const speckle::database::RecordID& modelID, const speckle::database::RecordID& projectID, + const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL, + const SettingList& settings) : + m_modelID(modelID), m_projectID(projectID), m_accountID(accountID), m_serverURL(serverURL), m_settings(settings) {} /*! Destructor */ diff --git a/SpeckleLib/Speckle/Database/Content/Record.h b/SpeckleLib/Speckle/Database/Content/Record.h index fdd1b3c..5d70542 100644 --- a/SpeckleLib/Speckle/Database/Content/Record.h +++ b/SpeckleLib/Speckle/Database/Content/Record.h @@ -28,12 +28,14 @@ namespace speckle::database { /*! Default constructor */ - Record() : base{} {} + Record() : base{active::utility::Guid{true}.operator active::utility::String(), + active::utility::Guid{true}.operator active::utility::String()} {} //TODO: Implement a better default for the ID /*! Constructor @param ID The record ID */ - Record(speckle::utility::String ID) : base{ID} {} + Record(speckle::utility::String ID, speckle::utility::String::Option globID = std::nullopt) : + base{ID, globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {} /*! Destructor */ diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp index b0a6b77..6438b2d 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -58,13 +58,11 @@ namespace { bool isExistingStore(active::utility::NameID& storeID) { if (storeID.id) return true; //We must have a store if the ID is populated - bool isStoreFound = false; API_Guid acID; if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectGuidFromName(String{storeID.name}, &acID)); statusCode != nominal) throw std::system_error(DocumentStoreCore::makeError(statusCode)); storeID.id = Guid{acID}; - isStoreFound = true; - return isStoreFound; + return storeID.id.operator bool(); //Returns true if the store ID is non-null, i.e. the object exists } //isExistingStore From 1f6bcbd947cdf1e17ba33e8945204cf1c81a7ace Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Mon, 16 Sep 2024 16:32:03 +0100 Subject: [PATCH 14/16] Not using ArchicadEverythingFilter yet DocumentCoreStore now records and applies document storage ID correctly --- .../Interface/Browser/Bridge/Send/GetSendFilters.cpp | 2 +- .../Database/Storage/DocumentStore/DocumentStoreCore.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp index 9829303..efddd60 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/GetSendFilters.cpp @@ -34,7 +34,7 @@ GetSendFilters::GetSendFilters() : BridgeMethod{"GetSendFilters", [&]() { --------------------------------------------------------------------*/ std::unique_ptr GetSendFilters::run() const { Vector filters; - filters.emplace_back(ArchicadEverythingFilter{}); + //filters.emplace_back(ArchicadEverythingFilter{}); //TODO: Implement as required filters.emplace_back(ArchicadSelectionFilter{}); return std::make_unique(filters); } //GetSendFilters::run diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp index 6438b2d..7fedccf 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -209,7 +209,7 @@ void DocumentStoreCore::writeStore() { API_Guid acID; if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_CreateUniqueObject(String{m_id.name}, &acID)); statusCode != nominal) throw std::system_error(makeError(statusCode)); - m_id = Guid{acID}; + m_id.id = Guid{acID}; } //Reserve the storage object in TW if (addon()->isSharedDocument()) { @@ -222,7 +222,7 @@ void DocumentStoreCore::writeStore() { //Write the new data GSHandle output = BMAllocateHandle(static_cast(toWrite.size()), ALLOCATE_CLEAR, 0); active::utility::Memory::copy(*output, toWrite.data(), toWrite.size(), toWrite.size()); - if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ModifyObject({Guid{m_id.id}}, nullptr, &output)); statusCode != nominal) + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ModifyObject(Guid{m_id.id}, nullptr, &output)); statusCode != nominal) throw std::system_error(makeError(statusCode)); BMKillHandle(&output); //Release the storage object in TW From ce6306c1de55be4e24046d4b6a256b7f138b8131 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Mon, 16 Sep 2024 22:54:55 +0100 Subject: [PATCH 15/16] CardMover should validate handler before constructing base Mover ReceiverModelCar constructor should also construct base ModelCard SenderModelCar didn't populate member filter DocumentStoreCore now loads objects when project reopened DocumentStoreCore uses defer for safer handle release DocumentStoreCore::resetStore must reset object ID DocumentStoreEngine must reset cache and DocumentStoreCore --- .../Connector/Record/Model/CardMover.cpp | 32 ++++++++++--------- .../Connector/Record/Model/CardMover.h | 5 --- .../Record/Model/ReceiverModelCard.h | 7 ++-- .../Record/Model/SenderModelCard.cpp | 11 ++++--- .../Connector/Record/Model/SenderModelCard.h | 3 +- .../DocumentStore/DocumentStoreCore.cpp | 24 ++++++++++++-- .../Storage/DocumentStore/DocumentStoreCore.h | 2 +- .../DocumentStore/DocumentStoreEngine.h | 5 ++- 8 files changed, 56 insertions(+), 33 deletions(-) diff --git a/SpeckleConnector/Connector/Record/Model/CardMover.cpp b/SpeckleConnector/Connector/Record/Model/CardMover.cpp index f2c1a60..48e9c94 100644 --- a/SpeckleConnector/Connector/Record/Model/CardMover.cpp +++ b/SpeckleConnector/Connector/Record/Model/CardMover.cpp @@ -21,6 +21,21 @@ namespace { ///Identity for a SenderModelCard const char* senderCardTypeName = "SenderModelCard"; + /*-------------------------------------------------------------------- + Ensure the handler is populated + + handler: The card handler to validate + + return: A reference to the handler + --------------------------------------------------------------------*/ + std::shared_ptr& validateHandler(std::shared_ptr& handler) { + if (!handler->empty()) + return handler; + handler->add(receiverCardTypeName); + handler->add(senderCardTypeName); + return handler; + } //CardMover::validateHandler + } ///The handler for model card packages @@ -32,8 +47,7 @@ std::shared_ptr CardMover::m_handler = std::make_sha handler: A package handler to reconstruct incoming packages --------------------------------------------------------------------*/ -CardMover::CardMover() : Mover{m_handler} { - validateHandler(); +CardMover::CardMover() : Mover{validateHandler(m_handler)} { } //CardMover::CardMover @@ -42,17 +56,5 @@ CardMover::CardMover() : Mover{m_handler} { outgoing: An outgoing package --------------------------------------------------------------------*/ -CardMover::CardMover(const active::serialise::Package& outgoing) : Mover{outgoing, m_handler} { - validateHandler(); +CardMover::CardMover(const active::serialise::Package& outgoing) : Mover{outgoing, validateHandler(m_handler)} { } //CardMover::CardMover - - -/*-------------------------------------------------------------------- - Ensure the handler is populated - --------------------------------------------------------------------*/ -void CardMover::validateHandler() { - if (!m_handler->empty()) - return; - m_handler->add(receiverCardTypeName); - m_handler->add(senderCardTypeName); -} //CardMover::validateHandler diff --git a/SpeckleConnector/Connector/Record/Model/CardMover.h b/SpeckleConnector/Connector/Record/Model/CardMover.h index 7e3fa0f..62bfe7c 100644 --- a/SpeckleConnector/Connector/Record/Model/CardMover.h +++ b/SpeckleConnector/Connector/Record/Model/CardMover.h @@ -27,11 +27,6 @@ namespace connector::record { 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 m_handler; }; diff --git a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h index 6357679..95c4217 100644 --- a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h +++ b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h @@ -33,9 +33,12 @@ namespace connector::record { @param hasDimissedWarning True if the user has already dismissed an alert to update @param bakedObjects The IDs of objects accepted in the receive */ - ReceiverModelCard(const speckle::utility::String& projectName, const speckle::utility::String& modelName, + ReceiverModelCard(const speckle::database::RecordID& projectID, const speckle::utility::String& projectName, + const speckle::database::RecordID& modelID, const speckle::utility::String& modelName, const speckle::database::RecordID& selectedVersion, const speckle::database::RecordID& latestVersion, - bool hasDimissedWarning, database::ElementIDList&& bakedObjects) : + const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL, + bool hasDimissedWarning, database::ElementIDList&& bakedObjects, const SettingList& settings) : + ModelCard{modelID, projectID, accountID, serverURL, settings}, m_projectName{projectName}, m_modelName{modelName}, m_selectedVersionID{selectedVersion}, m_latestVersionID{latestVersion}, m_hasDismissedUpdateWarning{hasDimissedWarning}, m_bakedObjectIDs{bakedObjects} {} /*! diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp index af8e31c..e122cc3 100644 --- a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp +++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp @@ -37,8 +37,10 @@ SenderModelCard::SenderModelCard() { filter: The filter applied when the model was sent --------------------------------------------------------------------*/ -SenderModelCard::SenderModelCard(const SendFilter& filter) { - +SenderModelCard::SenderModelCard(const SendFilter& filter, const speckle::database::RecordID& modelID, const speckle::database::RecordID& projectID, + const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL, const SettingList& settings) : + ModelCard{modelID, projectID, accountID, serverURL, settings}, m_filter(clone(filter)) +{ } //SenderModelCard::SenderModelCard @@ -47,8 +49,8 @@ SenderModelCard::SenderModelCard(const SendFilter& filter) { source: The object to copy --------------------------------------------------------------------*/ -SenderModelCard::SenderModelCard(const SenderModelCard& source) { - +SenderModelCard::SenderModelCard(const SenderModelCard& source) : ModelCard{source} { + m_filter = (source.m_filter) ? clone(*source.m_filter) : nullptr; } //SenderModelCard::SenderModelCard @@ -56,7 +58,6 @@ SenderModelCard::SenderModelCard(const SenderModelCard& source) { Destructor --------------------------------------------------------------------*/ SenderModelCard::~SenderModelCard() { - } //SenderModelCard::~SenderModelCard diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.h b/SpeckleConnector/Connector/Record/Model/SenderModelCard.h index 16d3493..0b3e010 100644 --- a/SpeckleConnector/Connector/Record/Model/SenderModelCard.h +++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.h @@ -27,7 +27,8 @@ namespace connector::record { Constructor @param filter The filter applied when the model was sent */ - SenderModelCard(const SendFilter& filter); + SenderModelCard(const SendFilter& filter, const speckle::database::RecordID& modelID, const speckle::database::RecordID& projectID, + const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL, const SettingList& settings); /*! Copy constructor @param source The object to copy diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp index 7fedccf..84e653e 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.cpp @@ -1,5 +1,6 @@ #include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h" +#include "Active/Utility/Defer.h" #include "Active/Utility/Memory.h" #include "Active/Utility/String.h" #include "Speckle/Environment/Addon.h" @@ -58,10 +59,27 @@ namespace { bool isExistingStore(active::utility::NameID& storeID) { if (storeID.id) return true; //We must have a store if the ID is populated + GS::UniString storeName{String{storeID.name}}; API_Guid acID; - if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectGuidFromName(String{storeID.name}, &acID)); statusCode != nominal) + if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectGuidFromName(storeName, &acID)); statusCode != nominal) throw std::system_error(DocumentStoreCore::makeError(statusCode)); storeID.id = Guid{acID}; + if (!storeID.id) { + GS::Array storedObjects; + ACAPI_AddOnObject_GetObjectList(&storedObjects); + for (auto iter = storedObjects.Enumerate(); iter != nullptr; ++iter) { + API_Guid objGuid = *iter; + GS::UniString objName; + GSHandle content = nullptr; + auto scope = active::utility::defer([&content](){ BMKillHandle(&content); }); + if (ACAPI_AddOnObject_GetObjectContent(objGuid, &objName, &content) == NoError) { + if (objName == storeName) { + storeID.id = Guid{objGuid}; + break; + } + } + } + } return storeID.id.operator bool(); //Returns true if the store ID is non-null, i.e. the object exists } //isExistingStore @@ -186,11 +204,11 @@ active::utility::Memory DocumentStoreCore::readStore() const { #ifdef ARCHICAD GS::UniString storeName{String{m_id.name}}; GSHandle storedData; + auto scoped = active::utility::defer([&storedData](){ BMKillHandle(&storedData); }); if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectContent(Guid{m_id.id}, &storeName, &storedData)); statusCode != nominal) throw std::system_error(makeError(statusCode)); //Copy the stored data into the result copyHandleToMemory(storedData, result); - BMKillHandle(&storedData); #endif return result; } //DocumentStoreCore::readStore @@ -221,10 +239,10 @@ void DocumentStoreCore::writeStore() { auto toWrite = buildStore(); //Write the new data GSHandle output = BMAllocateHandle(static_cast(toWrite.size()), ALLOCATE_CLEAR, 0); + auto scoped = active::utility::defer([&output](){ BMKillHandle(&output); }); active::utility::Memory::copy(*output, toWrite.data(), toWrite.size(), toWrite.size()); if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ModifyObject(Guid{m_id.id}, nullptr, &output)); statusCode != nominal) throw std::system_error(makeError(statusCode)); - BMKillHandle(&output); //Release the storage object in TW if (addon()->isSharedDocument()) { if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ReleaseObjects({Guid{m_id.id}})); statusCode != nominal) diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h index 77b98e0..c4a0585 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h @@ -104,7 +104,7 @@ namespace speckle::database { /*! Reset the stored data (some external change has invalidated previous data, e.g. the document was closed) */ - virtual void resetStore() = 0; + virtual void resetStore() { m_id.id.clear(); } // MARK: Subscriber functions diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h index 015975c..d911977 100644 --- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h @@ -135,7 +135,10 @@ namespace speckle::database { /*! Reset the stored data (some external change has invalidated previous data, e.g. the document was closed) */ - void resetStore() override { m_cache.reset(); } + void resetStore() override { + DocumentStoreCore::resetStore(); + m_cache.reset(); + } private: //Cached records from the document store From 03e74e5195bf0cd732913b887f8b109eb6386eba Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Tue, 17 Sep 2024 13:09:07 +0100 Subject: [PATCH 16/16] Version bump --- SpeckleConnector/Connector/Version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpeckleConnector/Connector/Version.h b/SpeckleConnector/Connector/Version.h index 5c79e01..97c24a3 100644 --- a/SpeckleConnector/Connector/Version.h +++ b/SpeckleConnector/Connector/Version.h @@ -7,7 +7,7 @@ namespace connector { static const unsigned int versionMinor = 2; - static const unsigned int versionPatch = 2; + static const unsigned int versionPatch = 3; }