introduce ConfigurationBuilder

This commit is contained in:
Michael Davidsaver
2015-12-11 09:59:15 -05:00
parent b3f78718b0
commit 3eb7775493
3 changed files with 104 additions and 6 deletions

View File

@@ -249,6 +249,52 @@ bool ConfigurationStack::tryGetPropertyAsString(const std::string& name, std::st
return false;
}
ConfigurationBuilder::ConfigurationBuilder() :stack(new ConfigurationStack) {}
ConfigurationBuilder& ConfigurationBuilder::push_env()
{
Configuration::shared_pointer env(new ConfigurationEnviron);
stack->push_back(env);
return *this;
}
ConfigurationBuilder& ConfigurationBuilder::push_map()
{
Configuration::shared_pointer env(new ConfigurationMap(mymap));
stack->push_back(env);
mymap.clear();
return *this;
}
ConfigurationBuilder&
ConfigurationBuilder::push_config(const Configuration::shared_pointer& conf)
{
stack->push_back(conf);
return *this;
}
ConfigurationBuilder&
ConfigurationBuilder::_add(const std::string& name, const std::string& val)
{
if(name.find_first_of(" \t\r\n")!=name.npos)
THROW_EXCEPTION2(std::invalid_argument, "Key name may not contain whitespace");
mymap[name] = val;
return *this;
}
Configuration::shared_pointer ConfigurationBuilder::build()
{
if(!mymap.empty())
THROW_EXCEPTION2(std::logic_error, "Missing call to .push_map()");
if(stack->size()==0) {
return Configuration::shared_pointer(new ConfigurationMap); // empty map
} else if(stack->size()==1) {
return stack->pop_back();
} else {
return stack;
}
}
void ConfigurationProviderImpl::registerConfiguration(const string &name, Configuration::shared_pointer const & configuration)
{
Lock guard(_mutex);
@@ -263,12 +309,15 @@ void ConfigurationProviderImpl::registerConfiguration(const string &name, Config
Configuration::shared_pointer ConfigurationProviderImpl::getConfiguration(const string &name)
{
std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
Lock guard(_mutex);
std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
if(configsIter != _configs.end())
{
return configsIter->second;
}
return Configuration::shared_pointer();
Configuration::shared_pointer env(new ConfigurationEnviron); // default to environment only
_configs[name] = env; // ensure that a later attempt to define this config will fail
return env;
}
ConfigurationProvider::shared_pointer configurationProvider;
@@ -280,8 +329,7 @@ ConfigurationProvider::shared_pointer ConfigurationFactory::getProvider()
if(configurationProvider.get() == NULL)
{
configurationProvider.reset(new ConfigurationProviderImpl());
// default
Configuration::shared_pointer systemConfig(new SystemConfigurationImpl());
Configuration::shared_pointer systemConfig(new ConfigurationEnviron);
configurationProvider->registerConfiguration("system", systemConfig);
}
return configurationProvider;

View File

@@ -155,6 +155,8 @@ class epicsShareClass ConfigurationMap: public Configuration
public:
typedef std::map<std::string, std::string> properties_t;
properties_t properties;
ConfigurationMap() {}
ConfigurationMap(const properties_t& p) :properties(p) {}
private:
virtual bool tryGetPropertyAsString(const std::string& name, std::string* val) const;
};
@@ -189,6 +191,27 @@ public:
inline size_t size() const {return confs.size();}
};
struct ConfigurationBuilder
{
ConfigurationBuilder();
ConfigurationBuilder& push_env();
ConfigurationBuilder& push_map();
ConfigurationBuilder& push_config(const Configuration::shared_pointer&);
template<typename V>
ConfigurationBuilder& add(const std::string& name, const V& val)
{
std::ostringstream strm;
strm<<val;
return _add(name, strm.str());
}
Configuration::shared_pointer build();
private:
ConfigurationBuilder& _add(const std::string& name, const std::string& val);
ConfigurationMap::properties_t mymap;
std::tr1::shared_ptr<ConfigurationStack> stack;
friend ConfigurationBuilder& operator<<(ConfigurationBuilder&, const std::string& s);
};
/**
* Configuration provider.
*/
@@ -249,6 +272,14 @@ public:
* @return configuration provider
*/
static ConfigurationProvider::shared_pointer getProvider();
static void registerConfiguration(const std::string &name, Configuration::shared_pointer const & configuration)
{
getProvider()->registerConfiguration(name, configuration);
}
static Configuration::shared_pointer getConfiguration(const std::string& name)
{
return getProvider()->getConfiguration(name);
}
private:
ConfigurationFactory() {};

View File

@@ -62,7 +62,6 @@ void testProp()
{
std::istringstream input(indata);
plist.load(input);
plist.list();
testOk1(!input.bad());
testOk1(input.eof());
}
@@ -96,6 +95,25 @@ static void setEnv(const char *name, const char *val)
testDiag("%s = \"%s\"", name, getenv(name));
}
static void testBuilder()
{
Configuration::shared_pointer C(ConfigurationBuilder()
.add("TESTKEY","value1")
.push_map()
.push_env()
.add("OTHERKEY","value3")
.push_map()
.build());
testOk1(C->getPropertyAsString("key", "X")=="X");
testOk1(C->getPropertyAsString("TESTKEY", "X")=="value1");
testOk1(C->getPropertyAsString("OTHERKEY", "X")=="value3");
setEnv("TESTKEY", "value2");
setEnv("OTHERKEY","value2");
testOk1(C->getPropertyAsString("TESTKEY", "X")=="value2");
testOk1(C->getPropertyAsString("OTHERKEY", "X")=="value3");
}
static void showAddr(const osiSockAddr& addr)
{
char buf[40];
@@ -183,8 +201,9 @@ void testConfig()
MAIN(configurationTest)
{
testPlan(44);
testPlan(49);
testProp();
testBuilder();
testConfig();
return testDone();
}