Skip to content

Commit

Permalink
feat(config): separate out config_builder and user_config components
Browse files Browse the repository at this point in the history
  • Loading branch information
lotem committed Feb 11, 2018
1 parent 45a7337 commit 9e9493b
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 49 deletions.
62 changes: 40 additions & 22 deletions src/rime/config/config_component.cc
Original file line number Diff line number Diff line change
Expand Up @@ -143,25 +143,51 @@ void Config::SetItem(an<ConfigItem> 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<ConfigData> 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<ConfigData>& 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<ConfigData> ConfigLoader::LoadConfig(ResourceResolver* resource_resolver,
const string& config_id) {
auto data = New<ConfigData>();
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<ConfigCompilerPlugin>(plugin));
}

Expand All @@ -182,7 +208,6 @@ struct MultiplePlugins : ConfigCompilerPlugin {
return ReviewedByAll(&ConfigCompilerPlugin::ReviewLinkOutput,
compiler, resource);
}

typedef bool (ConfigCompilerPlugin::*Reviewer)(ConfigCompiler* compiler,
an<ConfigResource> resource);
bool ReviewedByAll(Reviewer reviewer,
Expand All @@ -201,22 +226,15 @@ bool MultiplePlugins<Container>::ReviewedByAll(Reviewer reviewer,
return true;
}

an<ConfigData> 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<ConfigData>& wp(cache_[config_id]);
if (wp.expired()) { // create a new copy and load it
MultiplePlugins<decltype(plugins_)> 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<ConfigData> ConfigBuilder::LoadConfig(ResourceResolver* resource_resolver,
const string& config_id) {
MultiplePlugins<decltype(plugins_)> 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
56 changes: 47 additions & 9 deletions src/rime/config/config_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <rime/common.h>
#include <rime/component.h>
#include <rime/config/config_types.h>
#include <rime/resource.h>

namespace rime {

Expand Down Expand Up @@ -65,21 +66,58 @@ class Config : public Class<Config, const string&>, 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<ConfigResource> 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<ConfigData> LoadConfig(const string& config_id) = 0;
the<ResourceResolver> resource_resolver_;

private:
private:
an<ConfigData> GetConfigData(const string& file_name);
map<string, weak<ConfigData>> cache_;
the<ResourceResolver> resource_resolver_;
};

template <class Loader>
class ConfigComponent : public ConfigComponentBase {
public:
ConfigComponent(const ResourceType& resource_type = kConfigResourceType)
: ConfigComponentBase(resource_type) {}
ConfigComponent(function<void (Loader* loader)> setup)
: ConfigComponentBase(kConfigResourceType) {
setup(&loader_);
}
private:
an<ConfigData> LoadConfig(const string& config_id) override {
return loader_.LoadConfig(resource_resolver_.get(), config_id);
}
Loader loader_;
};

class ConfigLoader {
public:
RIME_API an<ConfigData> 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<ConfigData> LoadConfig(ResourceResolver* resource_resolver,
const string& config_id);
void InstallPlugin(ConfigCompilerPlugin *plugin);
bool ApplyPlugins(ConfigCompiler* compiler, an<ConfigResource> resource);
private:
vector<the<ConfigCompilerPlugin>> plugins_;
};

Expand Down
2 changes: 1 addition & 1 deletion src/rime/config/config_data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace rime {

ConfigData::~ConfigData() {
if (modified_ && !file_name_.empty())
if (auto_save_ && modified_ && !file_name_.empty())
SaveToFile(file_name_);
}

Expand Down
2 changes: 2 additions & 0 deletions src/rime/config/config_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<ConfigItem> root;

Expand All @@ -51,6 +52,7 @@ class ConfigData {

string file_name_;
bool modified_ = false;
bool auto_save_ = false;
};

} // namespace rime
Expand Down
28 changes: 20 additions & 8 deletions src/rime/core_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
[](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<ConfigLoader>({"config", "build/", ".yaml"});
r.Register("config", config_builder);
r.Register("schema", new SchemaComponent(config_builder));

auto user_config = new ConfigComponent<ConfigLoader>(
[](ConfigLoader* loader) {
loader->set_auto_save(true);
});
r.Register("user_config", user_config);
}

static void rime_core_finalize() {
Expand Down
4 changes: 2 additions & 2 deletions src/rime/lever/deployment_tasks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config> user_config(Config::Require("config")->Create("user"));
the<Config> 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) {
Expand Down Expand Up @@ -235,7 +235,7 @@ bool WorkspaceUpdate::Run(Deployer* deployer) {
LOG(INFO) << "finished updating schemas: "
<< success << " success, " << failure << " failure.";

the<Config> user_config(Config::Require("config")->Create("user"));
the<Config> 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));

Expand Down
6 changes: 3 additions & 3 deletions src/rime/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/rime/switcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion test/config_compiler_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<ConfigBuilder>);
config_.reset(component_->Create(test_config_id()));
}

Expand Down
7 changes: 5 additions & 2 deletions test/config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class RimeConfigTest : public ::testing::Test {
RimeConfigTest() = default;

virtual void SetUp() {
component_.reset(new ConfigComponent);
component_.reset(new ConfigComponent<ConfigLoader>);
config_.reset(component_->Create("config_test"));
}

Expand All @@ -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>(
[](ConfigLoader* loader) {
loader->set_auto_save(true);
}));
// find component
Config::Component* cc = Config::Require("test_config");
ASSERT_TRUE(cc != NULL);
Expand Down

0 comments on commit 9e9493b

Please sign in to comment.