ModelCardDatabase can retrieve a card by ID

Added numerous Send argument classes:
- ConversionResult (incomplete)
- SendError
- SendObject
- SendViaBrowserArgs (incomplete)
Send method looks up model card and account details, constructs send arguments
AccountDatabase can find an account by ID or server URL
Added DetachedMemoryStore
This commit is contained in:
Ralph Wessel
2024-10-01 17:24:59 +01:00
parent deee1e80c5
commit e148094c81
24 changed files with 838 additions and 81 deletions
@@ -31,6 +31,11 @@
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08452C9633A800CD343B /* EverythingSendFilter.cpp */; };
2192460D2CA3469D00CF5703 /* RootCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2192460B2CA3469D00CF5703 /* RootCollection.cpp */; };
219F30422C769283009834E9 /* ConfigTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219F30402C769282009834E9 /* ConfigTests.cpp */; };
21AEF9EB2CAB56E5000B8681 /* SendError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E32CAB56E5000B8681 /* SendError.cpp */; };
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */; };
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9EE2CAB5720000B8681 /* SendObject.cpp */; };
21AEF9F32CAC12D1000B8681 /* SendManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9F02CAC12D1000B8681 /* SendManager.cpp */; };
21AEF9FA2CAC3897000B8681 /* ConversionResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */; };
21B67CA32C769CB400FD64FC /* libActiveLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69EF52C64FE91008B6A06 /* libActiveLib.a */; };
21B67CA42C769CB400FD64FC /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69ECD2C64C035008B6A06 /* libArchicad27.a */; };
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21B67CA52C77329800FD64FC /* BaseBridge.cpp */; };
@@ -306,6 +311,16 @@
219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
219F30402C769282009834E9 /* ConfigTests.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = ConfigTests.cpp; sourceTree = "<group>"; };
219F30432C7693B6009834E9 /* Connector-AC27-Debug.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Connector-AC27-Debug.xctestplan"; sourceTree = SOURCE_ROOT; };
21AEF9E32CAB56E5000B8681 /* SendError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendError.cpp; sourceTree = "<group>"; };
21AEF9E42CAB56E5000B8681 /* SendError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendError.h; sourceTree = "<group>"; };
21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendViaBrowserArgs.cpp; sourceTree = "<group>"; };
21AEF9E62CAB56E5000B8681 /* SendViaBrowserArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendViaBrowserArgs.h; sourceTree = "<group>"; };
21AEF9ED2CAB5720000B8681 /* SendObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendObject.h; sourceTree = "<group>"; };
21AEF9EE2CAB5720000B8681 /* SendObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendObject.cpp; sourceTree = "<group>"; };
21AEF9F02CAC12D1000B8681 /* SendManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendManager.cpp; sourceTree = "<group>"; };
21AEF9F12CAC12D1000B8681 /* SendManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendManager.h; sourceTree = "<group>"; };
21AEF9F82CAC3897000B8681 /* ConversionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionResult.h; sourceTree = "<group>"; };
21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionResult.cpp; sourceTree = "<group>"; };
21B67CA52C77329800FD64FC /* BaseBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseBridge.cpp; sourceTree = "<group>"; };
21B67CA62C77329800FD64FC /* BaseBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseBridge.h; sourceTree = "<group>"; };
21B67CA72C77329800FD64FC /* GetSourceApplicationName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSourceApplicationName.cpp; sourceTree = "<group>"; };
@@ -945,6 +960,30 @@
path = ConnectorTests;
sourceTree = "<group>";
};
21AEF9E72CAB56E5000B8681 /* Arg */ = {
isa = PBXGroup;
children = (
21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */,
21AEF9F82CAC3897000B8681 /* ConversionResult.h */,
21AEF9E32CAB56E5000B8681 /* SendError.cpp */,
21AEF9E42CAB56E5000B8681 /* SendError.h */,
21AEF9EE2CAB5720000B8681 /* SendObject.cpp */,
21AEF9ED2CAB5720000B8681 /* SendObject.h */,
21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */,
21AEF9E62CAB56E5000B8681 /* SendViaBrowserArgs.h */,
);
path = Arg;
sourceTree = "<group>";
};
21AEF9F22CAC12D1000B8681 /* Serialise */ = {
isa = PBXGroup;
children = (
21AEF9F02CAC12D1000B8681 /* SendManager.cpp */,
21AEF9F12CAC12D1000B8681 /* SendManager.h */,
);
path = Serialise;
sourceTree = "<group>";
};
21B67CAB2C77329800FD64FC /* Base */ = {
isa = PBXGroup;
children = (
@@ -1029,6 +1068,7 @@
21D0BD5D2C89BFEA0077E104 /* Send */ = {
isa = PBXGroup;
children = (
21AEF9E72CAB56E5000B8681 /* Arg */,
21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */,
21D0BD952C8F13F30077E104 /* GetSendFilters.h */,
21D0BD8D2C8EE4490077E104 /* Send.cpp */,
@@ -1143,6 +1183,7 @@
21F69F092C677BC0008B6A06 /* Event */,
21F69F0E2C677BC0008B6A06 /* Interface */,
21D0BDD82C9387E60077E104 /* Record */,
21AEF9F22CAC12D1000B8681 /* Serialise */,
21B67CBA2C774C6500FD64FC /* Version.h */,
);
path = Connector;
@@ -1411,8 +1452,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
21AEF9FA2CAC3897000B8681 /* ConversionResult.cpp in Sources */,
21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */,
21B67CE32C78D1FB00FD64FC /* SayHiArg.cpp in Sources */,
21AEF9EB2CAB56E5000B8681 /* SendError.cpp in Sources */,
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */,
21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */,
21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */,
@@ -1427,11 +1470,13 @@
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */,
2192460D2CA3469D00CF5703 /* RootCollection.cpp in Sources */,
21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */,
21AEF9F32CAC12D1000B8681 /* SendManager.cpp in Sources */,
210CC8832C80E6A300610F58 /* TriggerEvent.cpp in Sources */,
21B67CEB2C78D27200FD64FC /* DocumentInfo.cpp in Sources */,
21B67CB92C774BFA00FD64FC /* GetConnectorVersion.cpp in Sources */,
21B67CD92C78C83800FD64FC /* TestBridge.cpp in Sources */,
214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */,
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */,
21FF70492CA1A7F400AAD99A /* RecordCollection.cpp in Sources */,
21B67CC02C775A0D00FD64FC /* GetDocumentInfo.cpp in Sources */,
21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */,
@@ -1442,6 +1487,7 @@
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */,
215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */,
21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */,
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */,
21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */,
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */,
21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */,
@@ -54,6 +54,9 @@ enum WarningString {
//Error strings (errors displayed in alerts)
enum ErrorString {
noSelectedModelItemsID = 1,
modelCardNotFoundID,
noProjectOpenID,
accountNotFoundID,
};
#endif //CONNECTOR_RESOURCE
@@ -71,6 +71,16 @@ ModelCardDatabase::ModelCardDatabase() {
ModelCardDatabase::~ModelCardDatabase() {}
/*--------------------------------------------------------------------
Get a specified card from the database
return: The requested card (nullptr on failure)
--------------------------------------------------------------------*/
ModelCard::Unique ModelCardDatabase::getCard(const speckle::utility::String& cardID) const {
return m_store->getObject(cardID);
} //ModelCardDatabase::getCard
/*--------------------------------------------------------------------
Get all model cards
@@ -29,6 +29,11 @@ namespace connector::database {
// MARK: - Functions (const)
/*!
Get a specified card from the database
@return The requested card (nullptr on failure)
*/
record::ModelCard::Unique getCard(const speckle::utility::String& cardID) const;
/*!
Get all model cards
@return All the cards
@@ -0,0 +1,63 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h"
#include "Active/Serialise/item/Wrapper/ValueWrap.h"
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
errorID,
cardID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"error"},
Identity{"modelCardId"},
};
}
/*--------------------------------------------------------------------
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 ConversionResult::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[errorID], errorID, element },
{ fieldID[cardID], cardID, element },
},
}.withType(&typeid(ConversionResult)));
return true;
} //ConversionResult::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ConversionResult::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(ConversionResult))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case errorID:
return std::make_unique<ValueWrap<String>>(message);
case cardID:
return std::make_unique<ValueWrap<String>>(modelCardID);
default:
return nullptr; //Requested an unknown index
}
} //ConversionResult::getCargo
@@ -0,0 +1,68 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT
#define CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Speckle/Utility/String.h"
namespace connector::interfac::browser::bridge {
/*!
A send error to return to the JS in the event of an error
*/
class ConversionResult final : public active::serialise::Package {
public:
enum class Status {
success = 1,
info,
warning,
error,
};
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
ConversionResult(const speckle::utility::String& errMess, const speckle::utility::String& card) : message{errMess}, modelCardID{card} {}
// MARK: - Public variables
///The error message
speckle::utility::String message;
///The ID of the model card associated with the data
speckle::utility::String modelCardID;
///The element conversion status
Status status = Status::info;
///For receive conversion reports, this is the id of the speckle object. For send, it's the host app object id.
speckle::utility::String sourceId;
///For receive conversion reports, this is the type of the speckle object. For send, it's the host app object type.
speckle::utility::String sourceType;
///For receive conversion reports, this is the id of the host app object. For send, it's the speckle object id.
speckle::utility::String resultId;
///For receive conversion reports, this is the type of the host app object. For send, it's the speckle object type.
speckle::utility::String resultType;
///The exception (nullopt = no exception)
SendError::Option error;
// 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;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT
@@ -0,0 +1,63 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Active/Serialise/item/Wrapper/ValueWrap.h"
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
errorID,
cardID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"error"},
Identity{"modelCardId"},
};
}
/*--------------------------------------------------------------------
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 SendError::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[errorID], errorID, element },
{ fieldID[cardID], cardID, element },
},
}.withType(&typeid(SendError)));
return true;
} //SendError::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SendError::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(SendError))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case errorID:
return std::make_unique<ValueWrap<String>>(message);
case cardID:
return std::make_unique<ValueWrap<String>>(modelCardID);
default:
return nullptr; //Requested an unknown index
}
} //SendError::getCargo
@@ -0,0 +1,54 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_ERROR
#define CONNECTOR_INTERFACE_BRIDGE_SEND_ERROR
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Speckle/Utility/String.h"
namespace connector::interfac::browser::bridge {
/*!
A send error to return to the JS in the event of an error
*/
class SendError final : public active::serialise::Package {
public:
// MARK: Types
///Optional
using Option = std::optional<SendError>;
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
SendError(const speckle::utility::String& errMess, const speckle::utility::String& card) : message{errMess}, modelCardID{card} {}
// MARK: - Public variables
///The error message
speckle::utility::String message;
///The ID of the model card associated with the data
speckle::utility::String modelCardID;
// 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;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_ERROR
@@ -0,0 +1,146 @@
#include "Connector/Interface/Browser/Bridge/Send/Send.h"
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
#include "Speckle/Serialise/Detached/Storage/DetachedMemoryStore.h"
#include "Speckle/Utility/Exception.h"
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
using namespace speckle::serialise;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
errorID,
cardID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"error"},
Identity{"modelCardId"},
};
/*!
A send error to return to the JS in the event of an error
*/
class SendError final : public active::serialise::Package {
public:
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
SendError(const String& errMess, const String& card) : message{errMess}, modelCardID{card} {}
// MARK: - Public variables
///The error message
String message;
///The ID of the model card associated with the data
String modelCardID;
// 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;
};
}
/*--------------------------------------------------------------------
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 SendError::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[errorID], errorID, element },
{ fieldID[cardID], cardID, element },
},
}.withType(&typeid(SendError)));
return true;
} //SendError::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SendError::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(SendError))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case errorID:
return std::make_unique<ValueWrap<String>>(message);
case cardID:
return std::make_unique<ValueWrap<String>>(modelCardID);
default:
return nullptr; //Requested an unknown index
}
} //SendError::getCargo
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Send::Send() : BridgeMethod{"Send", [&](const SendArgs& args) {
run(args);
}} {}
/*--------------------------------------------------------------------
Send a specified model
modelCardID: The ID of the model to send
--------------------------------------------------------------------*/
void Send::run(const String& modelCardID) const {
//Find the specified model card
auto modelCardDatabase = connector()->getModelCardDatabase();
auto modelCard = modelCardDatabase->getCard(modelCardID);
if (!modelCard) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, modelCardNotFoundID), modelCardID));
return;
}
//Get the active project
auto project = connector()->getActiveProject().lock();
if (!project) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, noProjectOpenID), modelCardID));
return;
}
DetachedMemoryStore detachedObjects;
} //Send::run
@@ -0,0 +1,53 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
#define CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Connector/Interface/Browser/Bridge/Config/Arg/ConnectorConfig.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
/*!
Class defining the primary content of a send
*/
class SendObject final : public active::serialise::Package {
public:
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
SendObject() {}
// MARK: - Public variables
///The root object id which should be used for creating the version
speckle::utility::String id;
///The total number of children
int32_t totalChildrenCount;
///JSON batches for the root object and child (detached) objects
std::vector<speckle::utility::String> batches;
// 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;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
@@ -0,0 +1,106 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Speckle/Record/Credentials/Account.h"
using namespace active::serialise;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
using namespace speckle::record::cred;
using namespace speckle::serialise;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
cardID,
projID,
modID,
tokenID,
serverID,
accID,
messageID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"modelCardId"},
Identity{"projectId"},
Identity{"modelId"},
Identity{"token"},
Identity{"serverUrl"},
Identity{"accountId"},
Identity{"message"},
};
}
/*--------------------------------------------------------------------
Constructor
modelCard: The model card to populate into the send info for the browser
account: The account linked to the send
--------------------------------------------------------------------*/
SendViaBrowserArgs::SendViaBrowserArgs(const ModelCard& modelCard, const Account& account) :
modelCardID(modelCard.getID()), projectID(modelCard.getProjectID()), modelID(modelCard.getModelID()), token{account.getToken()},
serverURL{account.getServerURL()}, accountID{account.getID()} {
} //SendViaBrowserArgs::SendViaBrowserArgs
/*--------------------------------------------------------------------
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 SendViaBrowserArgs::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[cardID], cardID, element },
{ fieldID[projID], projID, element },
{ fieldID[modID], modID, element },
{ fieldID[tokenID], tokenID, element },
{ fieldID[serverID], serverID, element },
{ fieldID[accID], accID, element },
{ fieldID[messageID], messageID, element },
},
}.withType(&typeid(SendViaBrowserArgs)));
return true;
} //SendViaBrowserArgs::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SendViaBrowserArgs::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(SendViaBrowserArgs))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case cardID:
return std::make_unique<StringWrap>(modelCardID);
case projID:
return std::make_unique<StringWrap>(projectID);
case modID:
return std::make_unique<StringWrap>(modelID);
case tokenID:
return std::make_unique<StringWrap>(token);
case serverID:
return std::make_unique<StringWrap>(serverURL);
case accID:
return std::make_unique<StringWrap>(accountID);
case messageID:
return std::make_unique<StringWrap>(message);
default:
return nullptr; //Requested an unknown index
}
} //SendViaBrowserArgs::getCargo
@@ -0,0 +1,78 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_VIA_BROWSER_ARGS
#define CONNECTOR_INTERFACE_BRIDGE_SEND_VIA_BROWSER_ARGS
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/String.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h"
#include "Speckle/Database/Identity/RecordID.h"
namespace speckle::record::cred {
class Account;
}
namespace connector::record {
class ModelCard;
}
namespace connector::interfac::browser::bridge {
class ConnectorConfig;
/*!
A commit of a project version (model) to the Speckle server
An object of this type is prepared by the Send bridge method
*/
class SendViaBrowserArgs final : public active::serialise::Package {
public:
// MARK: - Constructors
/*!
Constructor
@param modelCard The model card to populate into the send info for the browser
@param account The account linked to the send
*/
SendViaBrowserArgs(const connector::record::ModelCard& modelCard, const speckle::record::cred::Account& account);
// MARK: - Public variables
///ID of the model card driving the send request
speckle::database::RecordID modelCardID;
///The source project ID (from the model card)
speckle::database::RecordID projectID;
///The model ID (from the model card)
speckle::database::RecordID modelID;
///The account token (from the user account info)
speckle::utility::String token;
///The server URL (from the user account info)
speckle::utility::String serverURL;
///The user account ID
speckle::utility::String accountID;
///The send message
speckle::utility::String message; //TODO: Clarify what this is used for
///The conversion report (summarising the conversion results on an element-by-element basis)
std::vector<ConversionResult> sendConversionResults;
///The commit content
SendObject sendObject;
// 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;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_VIA_BROWSER_ARGS
@@ -4,86 +4,23 @@
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h"
#include "Speckle/Database/AccountDatabase.h"
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
#include "Speckle/Record/Credentials/Account.h"
#include "Speckle/Serialise/Detached/Storage/DetachedMemoryStore.h"
#include "Speckle/Utility/Exception.h"
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
using namespace speckle::serialise;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
errorID,
cardID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"error"},
Identity{"modelCardId"},
};
/*!
A send error to return to the JS in the event of an error
*/
class SendError final : public active::serialise::Package {
public:
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
SendError(const String& errMess, const String& card) : message{errMess}, modelCardID{card} {}
// MARK: - Public variables
///The error message
String message;
///The ID of the model card associated with the data
String modelCardID;
// 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 {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[errorID], errorID, element },
{ fieldID[cardID], cardID, element },
},
}.withType(&typeid(SendError)));
return true;
}
/*!
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 {
if (item.ownerType != &typeid(SendError))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case errorID:
return std::make_unique<ValueWrap<String>>(message);
case cardID:
return std::make_unique<ValueWrap<String>>(modelCardID);
default:
return nullptr; //Requested an unknown index
}
}
};
}
/*--------------------------------------------------------------------
@@ -100,7 +37,31 @@ Send::Send() : BridgeMethod{"Send", [&](const SendArgs& args) {
modelCardID: The ID of the model to send
--------------------------------------------------------------------*/
void Send::run(const String& modelCardID) const {
///TODO: Find and send selected elements - the following is a placeholder
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, noSelectedModelItemsID), modelCardID));
//Find the specified model card
auto modelCardDatabase = connector()->getModelCardDatabase();
auto modelCard = modelCardDatabase->getCard(modelCardID);
if (!modelCard) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, modelCardNotFoundID), modelCardID));
return;
}
auto accountDatabase = connector()->getAccountDatabase();
auto account = accountDatabase->getAccount(modelCard->getAccountID(), modelCard->getServerURL());
if (!account) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, accountNotFoundID), modelCardID));
return;
}
//Get the active project
auto project = connector()->getActiveProject().lock();
if (!project) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, noProjectOpenID), modelCardID));
return;
}
//We currently collect all detached object serialised data into a memory-based store - in future may be able to batch send and cache locally
DetachedMemoryStore detachedObjects;
auto result = std::make_unique<SendViaBrowserArgs>(modelCard, account);
getBridge()->sendEvent("sendByBrowser", std::move(result));
} //Send::run
@@ -19,6 +19,8 @@ namespace connector::record {
// MARK: - Types
using base = speckle::database::Record;
///Unique pointer
using Unique = std::unique_ptr<ModelCard>;
//List of card settings
using SettingList = active::container::Vector<connector::record::CardSetting>;
+3
View File
@@ -5,4 +5,7 @@
'STR#' 32604 "Error strings" {
/* [ 1] */ "No objects were found to convert. Please update your publish filter!"
/* [ 2] */ "The specified model card cannot be found. Try another card or create a new one"
/* [ 3] */ "Please open a project first"
/* [ 4] */ "The specified Speckle account cannot be found. Check that you have logged into your Speckle account with the Speckle Manager"
}
@@ -81,6 +81,27 @@ AccountDatabase::AccountDatabase(const active::file::Path& path) {
AccountDatabase::~AccountDatabase() {}
/*--------------------------------------------------------------------
Get a specified account. NB: The server URL is provided as a fallback for the search if the specified accountID is not found
accountID: The account ID (the primary search field)
serverURL: The server URL (a fallback search field if the account ID does not exist)
return: The requested account (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<Account> AccountDatabase::getAccount(const String& accountID, const String& serverURL) const {
//First attempt to find a matching account ID
auto matchingAccount = m_store->getObjects([&accountID](const auto& acc) { return acc.getID() == accountID; });
if (!matchingAccount.empty())
return matchingAccount.release(matchingAccount.begin());
//Alternatively seek an account with a matching server URL
matchingAccount = m_store->getObjects([&serverURL](const auto& acc) { return acc.getServerURL() == serverURL; });
if (!matchingAccount.empty())
return matchingAccount.release(matchingAccount.begin());
return nullptr;
} //AccountDatabase::getAccount
/*--------------------------------------------------------------------
Get all accounts
@@ -4,6 +4,10 @@
#include "Active/File/Path.h"
#include "Speckle/Record/Credentials/Account.h"
namespace speckle::record::cred {
class Account;
}
namespace speckle::database {
/*!
@@ -27,6 +31,13 @@ namespace speckle::database {
// MARK: - Functions (const)
/*!
Get a specified account. NB: The server URL is provided as a fallback for the search if the specified accountID is not found
@param accountID The account ID (the primary search field)
@param serverURL The server URL (a fallback search field if the account ID does not exist)
@return The requested account (nullptr on failure)
*/
std::unique_ptr<record::cred::Account> getAccount(const speckle::utility::String& accountID, const speckle::utility::String& serverURL) const;
/*!
Get all accounts
@return All the accounts
@@ -48,6 +48,17 @@ namespace speckle::record::cred {
// MARK: - Functions (const)
/*!
Get the account server URL
@return The account server URL (nullopt if none specified)
*/
speckle::utility::String getServerURL() const { return m_serverInfo.getURL(); }
/*!
Get the account token
@return The account token
*/
speckle::utility::String getToken() const { return m_token; }
// MARK: - Functions (mutating)
// MARK: - Serialisation
@@ -89,7 +89,7 @@ Cargo::Unique ServerInfo::getCargo(const Inventory::Item& item) const {
case frontEndID:
return std::make_unique<ValueWrap<bool>>(m_frontend2);
case urlID:
return std::make_unique<StringOptWrap>(m_url);
return std::make_unique<StringWrap>(m_url);
case migrationID:
return std::make_unique<Mover>(PackageUniqueWrap{m_migration});
default:
@@ -32,7 +32,7 @@ namespace speckle::record::cred {
*/
ServerInfo(const utility::String& name, const utility::String::Option company = std::nullopt,
const utility::String::Option version = std::nullopt, const utility::String::Option contact = std::nullopt,
const utility::String::Option description = std::nullopt, const utility::String::Option url = std::nullopt,
const utility::String::Option description = std::nullopt, const utility::String url = {},
bool isFrontEnd = false, std::unique_ptr<ServerMigration> migration = nullptr) :
m_name{name}, m_company{company}, m_version{version}, m_adminContact{contact}, m_description{description},
m_url{url}, m_frontend2{isFrontEnd}, m_migration{std::move(migration)} {}
@@ -90,7 +90,7 @@ namespace speckle::record::cred {
Get the URL
@return The URL
*/
const utility::String::Option& getURL() const { return m_url; }
const utility::String& getURL() const { return m_url; }
/*!
Get the migration history
@return The migration history (nullptr = no history)
@@ -143,7 +143,7 @@ namespace speckle::record::cred {
This field is not returned from the GQL API, it should be populated after construction.
See "Speckle.Core.Credentials.AccountManager"
*/
utility::String::Option m_url;
utility::String m_url;
///Server migration record
std::unique_ptr<ServerMigration> m_migration;
};
@@ -3,7 +3,6 @@
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Utility/BufferOut.h"
#include "Active/Utility/SHA256.h"
#include "Speckle/Serialise/Detached/DetachmentManager.h"
#include "Speckle/Utility/String.h"
using namespace active::serialise;
@@ -0,0 +1,52 @@
#ifndef SPECKLE_SERIALISE_DETACHED_MEMORY_STORE
#define SPECKLE_SERIALISE_DETACHED_MEMORY_STORE
#include "Speckle/Serialise/Detached/Storage/DetachedObjectStore.h"
#include <unordered_map>
namespace speckle::serialise {
/*!
Memory-based storage for detached objects
Detached object serialised data is held in a simple unordered_map keying the data against the object reference.
This class primarily intended for collecting the JSON from detached objects and holding until they can be forwarded to the server. The data
will not persist beyond this usage.
*/
class DetachedMemoryStore : public DetachedObjectStore, public std::unordered_map<database::RecordID, utility::String> {
public:
// MARK: - Types
using base = std::unordered_map<database::RecordID, utility::String>;
// MARK: - Functions (const)
/*!
Retrieve a detached object from storage
@param reference The required object reference
@return The object data (nullopt if the object cannot be found in storage)
*/
utility::String::Option retrieve(const database::RecordID& reference) const override {
if (auto iter = base::find(reference); iter != base::end())
return iter->second;
return std::nullopt;
}
// MARK: - Functions (mutating)
/*!
File a detached object in storage
@param reference The object reference (typically a hash generated from the object data)
@param data The object data (currently expected to be serialised as JSON)
@return True if the object was filed (typically ignored if it duplicates an object already in the store)
*/
bool file(const database::RecordID& reference, const utility::String& data) override {
return base::insert(std::make_pair(reference, data)).second;
}
};
}
#endif //SPECKLE_SERIALISE_DETACHED_MEMORY_STORE
@@ -28,7 +28,7 @@ namespace speckle::serialise {
@param reference The required object reference
@return The object data (nullopt if the object cannot be found in storage)
*/
virtual utility::String::Option retrieve(const database::RecordID& reference) = 0;
virtual utility::String::Option retrieve(const database::RecordID& reference) const = 0;
// MARK: - Functions (mutating)
@@ -38,7 +38,7 @@ namespace speckle::serialise {
@param data The object data (currently expected to be serialised as JSON)
@return True if the object was filed (typically rejected if it duplicates an object already in the store)
*/
virtual bool file(const database::RecordID& reference, const utility::String& data) const = 0;
virtual bool file(const database::RecordID& reference, const utility::String& data) = 0;
};
}
@@ -170,6 +170,7 @@
21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DetachmentManager.cpp; sourceTree = "<group>"; };
21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DetachedWrap.cpp; sourceTree = "<group>"; };
21AEF9DB2CAAA4EA000B8681 /* DetachedObjectStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedObjectStore.h; sourceTree = "<group>"; };
21AEF9DF2CAAC2AF000B8681 /* DetachedMemoryStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedMemoryStore.h; sourceTree = "<group>"; };
21B67CFE2C7CE15100FD64FC /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
21B67D092C7E0E8D00FD64FC /* ErrorReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorReport.h; sourceTree = "<group>"; };
21B67D0C2C7E0E8D00FD64FC /* ErrorReport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorReport.cpp; sourceTree = "<group>"; };
@@ -433,6 +434,7 @@
isa = PBXGroup;
children = (
21AEF9DB2CAAA4EA000B8681 /* DetachedObjectStore.h */,
21AEF9DF2CAAC2AF000B8681 /* DetachedMemoryStore.h */,
);
path = Storage;
sourceTree = "<group>";