introduce ConfigurationBuilder
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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() {};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user