Added speckle_type and unit properties to Record, BIMRecord, Element and Mesh classes

Defined (de)serialisation for LengthType
This commit is contained in:
Ralph Wessel
2024-10-04 21:03:54 +01:00
parent 3e2777a38f
commit 72cd75d2e6
10 changed files with 262 additions and 51 deletions
@@ -39,20 +39,20 @@ namespace connector::interfac::browser::bridge {
// 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;
};
@@ -1,5 +1,7 @@
#include "Speckle/Database/Content/BIMRecord.h"
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
#include "Speckle/Serialise/Units/LengthUnit.h"
#include "Speckle/Utility/Guid.h"
#include <array>
@@ -8,16 +10,20 @@ using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::utility;
using enum active::measure::LengthType;
namespace {
///Serialisation fields
enum FieldIndex {
applicID,
unitID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"applicationId"},
Identity{"unit"},
};
}
@@ -33,7 +39,8 @@ bool BIMRecord::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ Identity{fieldID[applicID]}, applicID, element },
{ Identity{fieldID[applicID]}, applicID, element, !m_applicationID.empty() },
{ Identity{fieldID[unitID]}, unitID, element, m_unit.operator bool() },
},
}.withType(&typeid(BIMRecord)));
return base::fillInventory(inventory);
@@ -54,7 +61,18 @@ Cargo::Unique BIMRecord::getCargo(const Inventory::Item& item) const {
switch (item.index) {
case applicID:
return std::make_unique<ValueWrap<BIMRecordID>>(m_applicationID);
case unitID:
return std::make_unique<ValueOptionWrap<active::measure::LengthType>>(m_unit);
default:
return nullptr; //Requested an unknown index
}
} //BIMRecord::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void BIMRecord::setDefault() {
m_applicationID.clear();
m_unit.reset();
} //BIMRecord::setDefault
@@ -1,6 +1,7 @@
#ifndef SPECKLE_DATABASE_BIM_RECORD
#define SPECKLE_DATABASE_BIM_RECORD
#include "Active/Setting/Values/Measurement/Units/LengthUnit.h"
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Database/Identity/BIMRecordID.h"
@@ -58,21 +59,27 @@ namespace speckle::database {
// 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)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///The BIM application record ID
BIMRecordID m_applicationID;
///The BIM record unit of length measurement
std::optional<active::measure::LengthType> m_unit = active::measure::LengthType::metre;
};
}
@@ -35,12 +35,12 @@ bool Record::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ Identity{fieldID[speckleIDID]}, active::database::record::FieldIndex::idIndex, element },
{ Identity{fieldID[speckleIDID]}, active::database::record::FieldIndex::idIndex, element, !getID().empty() },
},
}.withType(&typeid(base)));
inventory.merge(Inventory{
{
{ Identity{fieldID[speckleTypeID]}, speckleTypeID, element },
{ Identity{fieldID[speckleTypeID]}, speckleTypeID, element, !m_type.operator bool() },
},
}.withType(&typeid(Record)));
return true;
+3 -3
View File
@@ -31,8 +31,8 @@ namespace speckle::database {
@param globID The global ID
*/
Record(speckle::utility::String::Option ID = std::nullopt, speckle::utility::String::Option globID = std::nullopt) :
base{ID.value_or(active::utility::Guid{true}.operator active::utility::String()),
globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {}
base{ID.value_or(active::utility::Guid{}.operator active::utility::String()),
globID.value_or(active::utility::Guid{}.operator active::utility::String())} {}
/*!
Destructor
*/
@@ -44,7 +44,7 @@ namespace speckle::database {
Get the speckle type identifier
@return The speckle type (relevant objects should override as required, but "Base" is still considered a type on its own)
*/
virtual speckle::utility::String getSpeckleType() const { return "Base"; }
virtual speckle::utility::String getSpeckleType() const { return "speckle::database::Record"; }
// MARK: - Functions (mutating)
+10 -5
View File
@@ -1,15 +1,15 @@
#ifndef SPECKLE_PRIMITIVE_MESH
#define SPECKLE_PRIMITIVE_MESH
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Utility/String.h"
namespace speckle::primitive {
/*!
Class for a 3D mesh
*/
class Mesh : public active::serialise::Package {
*/
class Mesh : public speckle::database::Record {
public:
// MARK: - Constructors
@@ -24,6 +24,11 @@ namespace speckle::primitive {
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::primitive::Mesh"; }
// MARK: - Serialisation
@@ -31,13 +36,13 @@ namespace speckle::primitive {
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)
*/
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
+27 -22
View File
@@ -55,24 +55,29 @@ namespace speckle::record::element {
~Element();
/*!
Object cloning
@return A clone of this object
*/
Object cloning
@return A clone of this object
*/
Element* clonePtr() const override { return new Element{*this}; }
// MARK: - Functions (const)
/*!
Get the element body
@return An array of meshes from the element body (nullptr if no body data is available)
*/
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::record::element::Element"; }
/*!
Get the element body
@return An array of meshes from the element body (nullptr if no body data is available)
*/
virtual Body* getBody() const;
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
Get the (immutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
virtual const API_Elem_Head& getHead() const;
#endif
@@ -80,29 +85,29 @@ namespace speckle::record::element {
#ifdef ARCHICAD
/*!
Get the (mutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
Get the (mutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
virtual API_Elem_Head& getHead();
#endif
// 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;
private:
@@ -0,0 +1,55 @@
#include "Speckle/Serialise/Units/LengthUnit.h"
#include <algorithm>
#include <map>
using namespace active::measure;
using namespace active::utility;
using enum LengthType;
namespace {
//All recognised encoding types
std::map<LengthType, String> lengthNames = {
{ millimetre, "mm" },
{ centimetre, "cm" },
{ metre, "m" },
{ kilometre, "km" },
{ inch, "in" },
{ foot, "ft" },
{ yard, "yd" },
{ mile, "ml" },
};
} // namespace
/*--------------------------------------------------------------------
Convert a length unit name to a type
name: The length unit name
return: The length unit type (nullopt if no match found)
--------------------------------------------------------------------*/
std::optional<LengthType> speckle::serialise::lengthUnitFromName(const String& name) {
if (auto match = std::find_if(lengthNames.begin(), lengthNames.end(), [&](const auto& i){ return (i.second == name); });
match != lengthNames.end()) {
return match->first;
}
return std::nullopt;
} //encodingFromName
/*--------------------------------------------------------------------
Convert a length unit type to a name
lengthType: The length unit type
return: The name of the length unit type (nullopt if no match found)
--------------------------------------------------------------------*/
std::optional<String> speckle::serialise::nameFromLengthUnit(LengthType lengthType) {
if (auto match = lengthNames.find(lengthType); match != lengthNames.end()) {
return match->second;
}
return std::nullopt;
} //nameFromEncoding
@@ -0,0 +1,107 @@
#ifndef SPECKLE_SERIALISE_LENGTH_UNIT
#define SPECKLE_SERIALISE_LENGTH_UNIT
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
#include "Active/Setting/Values/Measurement/Units/LengthUnit.h"
namespace speckle::serialise {
/*!
Convert a length unit name to a type
@param name The length unit name
@return The length unit type (nullopt if no match found)
*/
std::optional<active::measure::LengthType> lengthUnitFromName(const active::utility::String& name);
/*!
Convert a length unit type to a name
@param lengthType The length unit type
@return The name of the length unit type (nullopt if no match found)
*/
std::optional<active::utility::String> nameFromLengthUnit(active::measure::LengthType lengthType);
}
namespace active::serialise {
// MARK: - Specialisations for length types
/*!
Read a length type value from the specified string
@param source The string to read
@return True if the data was successfully read
*/
inline std::pair<active::measure::LengthType, bool> readLengthTypeRefValue(const utility::String& source) {
using enum active::measure::LengthType;
if (auto converted = speckle::serialise::lengthUnitFromName(source); converted)
return {*converted, true};
return {metre, false};
} //ValueWrap<active::measure::LengthType>::read
/*!
Import the object from the specified string (specialisation for length type)
@param source The string to read
@return True if the data was successfully read
*/
template<> inline
bool ValueWrap<active::measure::LengthType>::read(const utility::String& source) {
auto result = readLengthTypeRefValue(source);
if (result.second)
base::get() = result.first;
return result.second;
} //ValueWrap<active::measure::LengthType>::read
/*!
Import the object from the specified string (specialisation for length type)
@param source The string to read
@return True if the data was successfully read
*/
template<> inline
bool ValueOptionWrap<active::measure::LengthType>::read(const utility::String& source) {
auto result = readLengthTypeRefValue(source);
if (result.second)
base::get() = result.first;
return result.second;
} //ValueWrap<active::measure::LengthType>::read
/*!
Export the object to the specified string (specialisation for length type)
@param dest The string to write the data to
@return True if the data was successfully written
*/
template<> inline
bool ValueWrap<active::measure::LengthType>::write(utility::String& dest) const {
if (auto name = speckle::serialise::nameFromLengthUnit(base::get()); name) {
dest = *name;
return true;
}
return false;
} //ValueWrap<active::measure::LengthType>::write
/*!
Export the object to the specified string (specialisation for length type)
@param dest The string to write the data to
@return True if the data was successfully written
*/
template<> inline
bool ValueOptionWrap<active::measure::LengthType>::write(utility::String& dest) const {
if (!base::get())
return false;
if (auto name = speckle::serialise::nameFromLengthUnit(*base::get()); name) {
dest = *name;
return true;
}
return false;
} //ValueOptionWrap<active::measure::LengthType>::write
}
#endif //SPECKLE_SERIALISE_LENGTH_UNIT
@@ -36,6 +36,7 @@
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 */; };
2196F2E32CB05BAF00450DFC /* LengthUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F2E22CB05BAF00450DFC /* LengthUnit.cpp */; };
2199881E2BD833830035E5EA /* libArchicad27.a in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21379E082AE47A6400A1584C /* libArchicad27.a */; };
21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */; };
21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */; };
@@ -162,6 +163,8 @@
219351AD2C62CC1A00E5A69C /* Guid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Guid.h; sourceTree = "<group>"; };
219351AE2C62CC1A00E5A69C /* String.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = String.cpp; sourceTree = "<group>"; };
219351AF2C62CC1A00E5A69C /* String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = String.h; sourceTree = "<group>"; };
2196F2DE2CB0566500450DFC /* LengthUnit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LengthUnit.h; sourceTree = "<group>"; };
2196F2E22CB05BAF00450DFC /* LengthUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LengthUnit.cpp; sourceTree = "<group>"; };
219712682BE7E2D500D9EF7E /* Serialisation.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Serialisation.md; sourceTree = "<group>"; };
21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedWrap.h; sourceTree = "<group>"; };
21AEF9B52CA5FA02000B8681 /* DetachedReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedReference.h; sourceTree = "<group>"; };
@@ -269,6 +272,7 @@
2167E27C2C49121F000827D3 /* CMakeLists.txt */,
21AEF9C72CA818EA000B8681 /* Detached */,
21F69F3A2C6B880B008B6A06 /* JSBase */,
2196F2DF2CB0566500450DFC /* Units */,
219712682BE7E2D500D9EF7E /* Serialisation.md */,
);
path = Serialise;
@@ -407,6 +411,15 @@
path = Utility;
sourceTree = "<group>";
};
2196F2DF2CB0566500450DFC /* Units */ = {
isa = PBXGroup;
children = (
2196F2E22CB05BAF00450DFC /* LengthUnit.cpp */,
2196F2DE2CB0566500450DFC /* LengthUnit.h */,
);
path = Units;
sourceTree = "<group>";
};
219987FA2BD708BC0035E5EA /* SpeckleLibDoctest */ = {
isa = PBXGroup;
children = (
@@ -780,6 +793,7 @@
21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */,
21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */,
219246082CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp in Sources */,
2196F2E32CB05BAF00450DFC /* LengthUnit.cpp in Sources */,
21F93AEC2B2F406E009A2C5B /* Addon.cpp in Sources */,
215F087D2CA18E1400CD343B /* Element.cpp in Sources */,
21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */,