Added DocumentStoreCore

Added DocumentStoreEngine
Added Addon::isSharedDocument
This commit is contained in:
Ralph Wessel
2024-09-10 22:28:29 +01:00
parent 7fe5ba6e9d
commit 7d9f939b8b
9 changed files with 609 additions and 4 deletions
@@ -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 {
@@ -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 <ACAPinc.h>
#include <BM.hpp>
#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<DocumentStoreCore::Status>(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<int>(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<API_Guid, short> 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<GSSize>(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
@@ -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, ///<No errors logged
badParameter, ///<The data supplied to an SDK function call was invalid
badID, ///<The ID for the stored data is invalid
error, ///<An unidentified error occurred
};
// MARK: - Static functions
/*!
Make an error code for DocumentStore processing
@return An STL error code
*/
static std::error_code makeError(DocumentStoreCore::Status code);
// MARK: - Constructors
/*!
Default constructor
@param id The document storage identifier
*/
DocumentStoreCore(const active::utility::NameID& id) : m_id(id) {}
/*!
Destructor
*/
virtual ~DocumentStoreCore() {}
// MARK: - Function (const)
/*!
Get the database id
@return The database id
*/
const active::utility::NameID& getID() const { return m_id; }
protected:
/*!
Read the data stored in the document (should be lazy-loading, only at the point where data is actually requested)
@return The stored data (empty if the data doesn't exist)
*/
active::utility::Memory readStore() const;
/*!
Write the data to document storage (currently happens at every change - could implement delayed storage until the point of send/save)
*/
void writeStore();
/*!
Build new store data from the latest records
@return Data to store from the latest records
*/
virtual active::utility::Memory buildStore() = 0;
/*!
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;
/*!
Reset the stored data (some external change has invalidated previous data, e.g. the document was closed)
*/
virtual void resetStore() = 0;
private:
///The database ID (mutable to allow lazy loading when data is accessed)
mutable active::utility::NameID m_id;
};
}
#endif //SPECKLE_DATABASE_DOCUMENT_STORE_CORE
@@ -0,0 +1,283 @@
#ifndef SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
#define SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
#include "Active/Database/Storage/DBaseEngine.h"
#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"
#include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <algorithm>
#include <ranges>
namespace speckle::database {
///Concept for the ability to store objects in a document
template<typename Obj, typename Transport>
concept DocumentStorable = std::is_base_of_v<active::serialise::Cargo, Obj> &&
std::is_base_of_v<active::serialise::Transport, Transport>;
/*!
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<typename Obj, typename Transport, typename ObjID = utility::String>
requires DocumentStorable<Obj, Transport>
class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine<Obj, ObjID, utility::String, utility::String> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<Obj, ObjID, utility::String, utility::String>;
using Filter = base::Filter;
using Cache = active::database::RecordCache<Obj, ObjID>;
// 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<Cache>(*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<Obj> 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<Obj> 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<Obj> 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<Cache> m_cache;
};
/*--------------------------------------------------------------------
Get the cache of records built from the data stored in the document
return: The cached records (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
typename DocumentStoreEngine<Obj, Transport, ObjID>::Cache* DocumentStoreEngine<Obj, Transport, ObjID>::getCache() const {
if (m_cache)
return m_cache;
//Read the data stored in the document
auto storedData = readStore();
m_cache = std::make_unique<Cache>();
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<active::serialise::Cargo&&>(*m_cache), active::serialise::Identity{}, storedData);
return m_cache;
} //DocumentStoreEngine<Obj, Transport, ObjID>::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<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
std::unique_ptr<Obj> DocumentStoreEngine<Obj, Transport, ObjID>::getObject(const ObjID& ID, utility::String::Option tableID,
utility::String::Option documentID) const {
auto cache = getCache();
return cache ? cache->read(ID) : nullptr;
} //DocumentStoreEngine<Obj, Transport, ObjID>::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<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
active::container::Vector<Obj> DocumentStoreEngine<Obj, Transport, ObjID>::getObjects(utility::String::Option tableID,
utility::String::Option documentID) const {
auto cache = getCache();
return cache ? cache->read() : nullptr;
} //DocumentStoreEngine<Obj, Transport, ObjID>::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<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
active::container::Vector<Obj> DocumentStoreEngine<Obj, Transport, ObjID>::getObjects(const Filter& filter, utility::String::Option tableID,
utility::String::Option documentID) const {
auto cache = getCache();
return cache ? cache->read(filter) : nullptr;
} //DocumentStoreEngine<Obj, Transport, ObjID>::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<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
void DocumentStoreEngine<Obj, Transport, ObjID>::erase(const ObjID& ID, utility::String::Option tableID,
utility::String::Option documentID) const {
auto cache = getCache();
if (cache)
cache->erase(ID);
} //DocumentStoreEngine<Obj, Transport, ObjID>::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<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
void DocumentStoreEngine<Obj, Transport, ObjID>::erase(utility::String::Option tableID, utility::String::Option documentID) const {
auto cache = getCache();
if (cache)
cache->erase();
} //DocumentStoreEngine<Obj, Transport, ObjID>::erase
/*--------------------------------------------------------------------
Build new store data from the latest records
return: Data to store from the latest records
--------------------------------------------------------------------*/
template<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
active::utility::Memory DocumentStoreEngine<Obj, Transport, ObjID>::buildStore() {
active::utility::Memory result;
auto cache = getCache();
if (!cache)
cache = std::make_unique<Cache>(); //We still want to export an empty cache object even if it contains no records
//Export the cached records
Transport().send(std::forward<active::serialise::Cargo&&>(*m_cache), active::serialise::Identity{}, result);
return result;
} //DocumentStoreEngine<Obj, Transport, ObjID>::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<typename Obj, typename Transport, typename ObjID>
requires DocumentStorable<Obj, Transport>
active::utility::Memory DocumentStoreEngine<Obj, Transport, ObjID>::mergeStore(const active::utility::Memory& toMerge) {
//Import the incoming records from the data to merge
Cache incoming;
Transport().receive(std::forward<active::serialise::Cargo&&>(incoming), active::serialise::Identity{}, toMerge);
//Get the data currently stored in the document
auto cache = getCache();
if (!cache)
cache = std::make_unique<Cache>(); //We still want to export an empty cache object even if it contains no records
cache->merge(incoming);
return buildStore();
} //DocumentStoreEngine<Obj, Transport, ObjID>::mergeStore
}
#endif //SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
+17 -1
View File
@@ -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
+5
View File
@@ -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)
@@ -102,8 +102,8 @@ namespace speckle::interfac::browser {
--------------------------------------------------------------------*/
template<typename FunctionBinding>
bool JSPortal<FunctionBinding>::install(std::shared_ptr<JSObject<FunctionBinding>> 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<FunctionBinding>::install
+6
View File
@@ -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
/*!
@@ -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 = "<group>"; };
21D0BD572C8910400077E104 /* UserInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserInfo.cpp; sourceTree = "<group>"; };
21D0BD582C8910400077E104 /* UserInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInfo.h; sourceTree = "<group>"; };
21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentStoreCore.cpp; sourceTree = "<group>"; };
21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreCore.h; sourceTree = "<group>"; };
21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreEngine.h; sourceTree = "<group>"; };
21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = "<group>"; };
21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = "<group>"; };
21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = "<group>"; };
@@ -293,8 +299,9 @@
children = (
21D0BD1D2C86F0280077E104 /* AccountDatabase.cpp */,
21D0BD1E2C86F0280077E104 /* AccountDatabase.h */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BD272C86FC350077E104 /* Content */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BDB02C8F8AB60077E104 /* Storage */,
);
path = Database;
sourceTree = "<group>";
@@ -318,6 +325,24 @@
path = Identity;
sourceTree = "<group>";
};
21D0BDAF2C8F8AB60077E104 /* DocumentStore */ = {
isa = PBXGroup;
children = (
21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */,
21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */,
21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */,
);
path = DocumentStore;
sourceTree = "<group>";
};
21D0BDB02C8F8AB60077E104 /* Storage */ = {
isa = PBXGroup;
children = (
21D0BDAF2C8F8AB60077E104 /* DocumentStore */,
);
path = Storage;
sourceTree = "<group>";
};
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 */,