From 9e9493b313336174c943e68543a238f9c3876917 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Sat, 10 Feb 2018 11:06:56 +0800 Subject: [PATCH] feat(config): separate out config_builder and user_config components --- src/rime/config/config_component.cc | 62 +++++++++++++++++++---------- src/rime/config/config_component.h | 56 +++++++++++++++++++++----- src/rime/config/config_data.cc | 2 +- src/rime/config/config_data.h | 2 + src/rime/core_module.cc | 28 +++++++++---- src/rime/lever/deployment_tasks.cc | 4 +- src/rime/schema.h | 6 +-- src/rime/switcher.cc | 2 +- test/config_compiler_test.cc | 2 +- test/config_test.cc | 7 +++- 10 files changed, 122 insertions(+), 49 deletions(-) diff --git a/src/rime/config/config_component.cc b/src/rime/config/config_component.cc index 7b9387386a..f5ff15dc66 100644 --- a/src/rime/config/config_component.cc +++ b/src/rime/config/config_component.cc @@ -143,25 +143,51 @@ void Config::SetItem(an item) { set_modified(); } -static const ResourceType kConfigResourceType = { +const ResourceType ConfigComponentBase::kConfigResourceType = { "config", "", ".yaml", }; -ConfigComponent::ConfigComponent() +ConfigComponentBase::ConfigComponentBase(const ResourceType& resource_type) : resource_resolver_( - Service::instance().CreateResourceResolver(kConfigResourceType)) { + Service::instance().CreateResourceResolver(resource_type)) { } -ConfigComponent::~ConfigComponent() { +ConfigComponentBase::~ConfigComponentBase() { } -Config* ConfigComponent::Create(const string& file_name) { +Config* ConfigComponentBase::Create(const string& file_name) { return new Config(GetConfigData(file_name)); } -void ConfigComponent::InstallPlugin(ConfigCompilerPlugin* plugin) { +an ConfigComponentBase::GetConfigData(const string& file_name) { + auto config_id = resource_resolver_->ToResourceId(file_name); + // keep a weak reference to the shared config data in the component + weak& wp(cache_[config_id]); + if (wp.expired()) { // create a new copy and load it + auto data = LoadConfig(config_id); + wp = data; + return data; + } + // obtain the shared copy + return wp.lock(); +} + +an ConfigLoader::LoadConfig(ResourceResolver* resource_resolver, + const string& config_id) { + auto data = New(); + data->LoadFromFile( + resource_resolver->ResolvePath(config_id).string(), nullptr); + data->set_auto_save(auto_save_); + return data; +} + +ConfigBuilder::ConfigBuilder() {} + +ConfigBuilder::~ConfigBuilder() {} + +void ConfigBuilder::InstallPlugin(ConfigCompilerPlugin* plugin) { plugins_.push_back(the(plugin)); } @@ -182,7 +208,6 @@ struct MultiplePlugins : ConfigCompilerPlugin { return ReviewedByAll(&ConfigCompilerPlugin::ReviewLinkOutput, compiler, resource); } - typedef bool (ConfigCompilerPlugin::*Reviewer)(ConfigCompiler* compiler, an resource); bool ReviewedByAll(Reviewer reviewer, @@ -201,22 +226,15 @@ bool MultiplePlugins::ReviewedByAll(Reviewer reviewer, return true; } -an ConfigComponent::GetConfigData(const string& file_name) { - auto config_id = resource_resolver_->ToResourceId(file_name); - // keep a weak reference to the shared config data in the component - weak& wp(cache_[config_id]); - if (wp.expired()) { // create a new copy and load it - MultiplePlugins multiple_plugins(plugins_); - ConfigCompiler compiler(resource_resolver_.get(), &multiple_plugins); - auto resource = compiler.Compile(file_name); - if (resource->loaded && !compiler.Link(resource)) { - LOG(ERROR) << "error loading config from: " << file_name; - } - wp = resource->data; - return resource->data; +an ConfigBuilder::LoadConfig(ResourceResolver* resource_resolver, + const string& config_id) { + MultiplePlugins multiple_plugins(plugins_); + ConfigCompiler compiler(resource_resolver, &multiple_plugins); + auto resource = compiler.Compile(config_id); + if (resource->loaded && !compiler.Link(resource)) { + LOG(ERROR) << "error building config: " << config_id; } - // obtain the shared copy - return wp.lock(); + return resource->data; } } // namespace rime diff --git a/src/rime/config/config_component.h b/src/rime/config/config_component.h index 3c0720a6ac..39895c28db 100644 --- a/src/rime/config/config_component.h +++ b/src/rime/config/config_component.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace rime { @@ -65,21 +66,58 @@ class Config : public Class, public ConfigItemRef { class ConfigCompiler; class ConfigCompilerPlugin; -class ResourceResolver; struct ConfigResource; -class ConfigComponent : public Config::Component { +class ConfigComponentBase : public Config::Component { public: - RIME_API ConfigComponent(); - ~ConfigComponent(); - Config* Create(const string& file_name); - void InstallPlugin(ConfigCompilerPlugin *plugin); - bool ApplyPlugins(ConfigCompiler* compiler, an resource); + RIME_API static const ResourceType kConfigResourceType; + RIME_API ConfigComponentBase(const ResourceType& resource_type); + RIME_API ~ConfigComponentBase(); + RIME_API Config* Create(const string& file_name); + + protected: + virtual an LoadConfig(const string& config_id) = 0; + the resource_resolver_; -private: + private: an GetConfigData(const string& file_name); map> cache_; - the resource_resolver_; +}; + +template + class ConfigComponent : public ConfigComponentBase { + public: + ConfigComponent(const ResourceType& resource_type = kConfigResourceType) + : ConfigComponentBase(resource_type) {} + ConfigComponent(function setup) + : ConfigComponentBase(kConfigResourceType) { + setup(&loader_); + } + private: + an LoadConfig(const string& config_id) override { + return loader_.LoadConfig(resource_resolver_.get(), config_id); + } + Loader loader_; +}; + +class ConfigLoader { + public: + RIME_API an LoadConfig(ResourceResolver* resource_resolver, + const string& config_id); + void set_auto_save(bool auto_save) { auto_save_ = auto_save; } + private: + bool auto_save_ = false; +}; + +class ConfigBuilder { + public: + RIME_API ConfigBuilder(); + RIME_API virtual ~ConfigBuilder(); + RIME_API an LoadConfig(ResourceResolver* resource_resolver, + const string& config_id); + void InstallPlugin(ConfigCompilerPlugin *plugin); + bool ApplyPlugins(ConfigCompiler* compiler, an resource); + private: vector> plugins_; }; diff --git a/src/rime/config/config_data.cc b/src/rime/config/config_data.cc index 47969f5375..980c1042da 100644 --- a/src/rime/config/config_data.cc +++ b/src/rime/config/config_data.cc @@ -16,7 +16,7 @@ namespace rime { ConfigData::~ConfigData() { - if (modified_ && !file_name_.empty()) + if (auto_save_ && modified_ && !file_name_.empty()) SaveToFile(file_name_); } diff --git a/src/rime/config/config_data.h b/src/rime/config/config_data.h index c7305f84be..c983360cff 100644 --- a/src/rime/config/config_data.h +++ b/src/rime/config/config_data.h @@ -37,6 +37,7 @@ class ConfigData { const string& file_name() const { return file_name_; } bool modified() const { return modified_; } void set_modified() { modified_ = true; } + void set_auto_save(bool auto_save) { auto_save_ = auto_save; } an root; @@ -51,6 +52,7 @@ class ConfigData { string file_name_; bool modified_ = false; + bool auto_save_ = false; }; } // namespace rime diff --git a/src/rime/core_module.cc b/src/rime/core_module.cc index 907d970770..3827531891 100644 --- a/src/rime/core_module.cc +++ b/src/rime/core_module.cc @@ -20,14 +20,26 @@ static void rime_core_initialize() { LOG(INFO) << "registering core components."; Registry& r = Registry::instance(); - auto config = new ConfigComponent; - config->InstallPlugin(new AutoPatchConfigPlugin); - config->InstallPlugin(new DefaultConfigPlugin); - config->InstallPlugin(new LegacyPresetConfigPlugin); - config->InstallPlugin(new LegacyDictionaryConfigPlugin); - config->InstallPlugin(new BuildInfoPlugin); - r.Register("config", config); - r.Register("schema", new SchemaComponent(config)); + auto config_builder = new ConfigComponent( + [](ConfigBuilder* builder) { + builder->InstallPlugin(new AutoPatchConfigPlugin); + builder->InstallPlugin(new DefaultConfigPlugin); + builder->InstallPlugin(new LegacyPresetConfigPlugin); + builder->InstallPlugin(new LegacyDictionaryConfigPlugin); + builder->InstallPlugin(new BuildInfoPlugin); + }); + r.Register("config_builder", config_builder); + + //auto config_loader = + // new ConfigComponent({"config", "build/", ".yaml"}); + r.Register("config", config_builder); + r.Register("schema", new SchemaComponent(config_builder)); + + auto user_config = new ConfigComponent( + [](ConfigLoader* loader) { + loader->set_auto_save(true); + }); + r.Register("user_config", user_config); } static void rime_core_finalize() { diff --git a/src/rime/lever/deployment_tasks.cc b/src/rime/lever/deployment_tasks.cc index 9620928449..0d72c11dde 100644 --- a/src/rime/lever/deployment_tasks.cc +++ b/src/rime/lever/deployment_tasks.cc @@ -66,7 +66,7 @@ bool DetectModifications::Run(Deployer* deployer) { // TODO: store as 64-bit number to avoid the year 2038 problem int last_build_time = 0; { - the user_config(Config::Require("config")->Create("user")); + the user_config(Config::Require("user_config")->Create("user")); user_config->GetInt("var/last_build_time", &last_build_time); } if (last_modified > (time_t)last_build_time) { @@ -235,7 +235,7 @@ bool WorkspaceUpdate::Run(Deployer* deployer) { LOG(INFO) << "finished updating schemas: " << success << " success, " << failure << " failure."; - the user_config(Config::Require("config")->Create("user")); + the user_config(Config::Require("user_config")->Create("user")); // TODO: store as 64-bit number to avoid the year 2038 problem user_config->SetInt("var/last_build_time", (int)time(NULL)); diff --git a/src/rime/schema.h b/src/rime/schema.h index ed2e0b92ab..9ecdb14b33 100644 --- a/src/rime/schema.h +++ b/src/rime/schema.h @@ -42,15 +42,15 @@ class Schema { class SchemaComponent : public Config::Component { public: - SchemaComponent(ConfigComponent* config_component) + SchemaComponent(Config::Component* config_component) : config_component_(config_component) { } // NOTE: creates `Config` for the schema Config* Create(const string& schema_id) override; private: - // we do not own the ConfigComponent, do not try to deallocate it + // we do not own the config component, do not try to deallocate it // also be careful that there is no guarantee it will outlive us - ConfigComponent* config_component_; + Config::Component* config_component_; }; } // namespace rime diff --git a/src/rime/switcher.cc b/src/rime/switcher.cc index 94108cf9a2..ee4171b02b 100644 --- a/src/rime/switcher.cc +++ b/src/rime/switcher.cc @@ -27,7 +27,7 @@ Switcher::Switcher(const Ticket& ticket) : Processor(ticket) { context_->select_notifier().connect( [this](Context* ctx) { OnSelect(ctx); }); - user_config_.reset(Config::Require("config")->Create("user")); + user_config_.reset(Config::Require("user_config")->Create("user")); InitializeComponents(); LoadSettings(); RestoreSavedOptions(); diff --git a/test/config_compiler_test.cc b/test/config_compiler_test.cc index fe0f8c7b3f..fbd905c6fa 100644 --- a/test/config_compiler_test.cc +++ b/test/config_compiler_test.cc @@ -17,7 +17,7 @@ class RimeConfigCompilerTestBase : public ::testing::Test { virtual string test_config_id() const = 0; virtual void SetUp() { - component_.reset(new ConfigComponent); + component_.reset(new ConfigComponent); config_.reset(component_->Create(test_config_id())); } diff --git a/test/config_test.cc b/test/config_test.cc index 2bd681cb0a..71980201b7 100644 --- a/test/config_test.cc +++ b/test/config_test.cc @@ -16,7 +16,7 @@ class RimeConfigTest : public ::testing::Test { RimeConfigTest() = default; virtual void SetUp() { - component_.reset(new ConfigComponent); + component_.reset(new ConfigComponent); config_.reset(component_->Create("config_test")); } @@ -30,7 +30,10 @@ class RimeConfigTest : public ::testing::Test { TEST(RimeConfigComponentTest, RoundTrip) { // registration Registry& r = Registry::instance(); - r.Register("test_config", new ConfigComponent); + r.Register("test_config", new ConfigComponent( + [](ConfigLoader* loader) { + loader->set_auto_save(true); + })); // find component Config::Component* cc = Config::Require("test_config"); ASSERT_TRUE(cc != NULL);