#pragma once #include "error/instance.h" #include "error/result.h" #include "logger.h" #include "objects/base/instance.h" #include "objects/base/refstate.h" #include "objects/meta.h" #include "panic.h" #include #include class Workspace; class DataModel; class Service; // The root instance to all objects in the hierarchy class DataModel : public Instance { private: void DeserializeService(pugi::xml_node node); static void cloneService(std::shared_ptr target, std::shared_ptr, RefState<_RefStatePropertyCell>); public: const static InstanceType TYPE; std::map> services; std::optional currentFile; DataModel(); void Init(); static inline std::shared_ptr New() { return std::make_shared(); }; virtual const InstanceType* GetClass() override; // Inserts a service if it doesn't already exist fallible InsertService(std::string name) { if (services.count(name) != 0) return fallible(ServiceAlreadyExists(name)); if (!INSTANCE_MAP[name] || (INSTANCE_MAP[name]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) { Logger::fatalErrorf("Attempt to create instance of unknown type %s", name); panic(); } services[name] = std::dynamic_pointer_cast(INSTANCE_MAP[name]->constructor()); AddChild(std::dynamic_pointer_cast(services[name])); return {}; } result, NoSuchService> GetService(std::string className); result>, NoSuchService> FindService(std::string className); template result, NoSuchService> GetService() { auto result = GetService(T::TYPE.className); if (result.isError()) return result.error().value(); return std::dynamic_pointer_cast(result.success().value()); } template std::optional> FindService() { auto result = FindService(T::TYPE.className); if (result.isError()) return result.error().value(); return std::dynamic_pointer_cast(result.success().value()); } // Saving/loading inline bool HasFile() { return this->currentFile.has_value(); } void SaveToFile(std::optional path = std::nullopt); static std::shared_ptr LoadFromFile(std::string path); std::shared_ptr CloneModel(); };