| 1 | #pragma once
|
|---|
| 2 |
|
|---|
| 3 | #include <map>
|
|---|
| 4 | #include <string>
|
|---|
| 5 |
|
|---|
| 6 | #include <boost/foreach.hpp>
|
|---|
| 7 | #include <boost/optional.hpp>
|
|---|
| 8 | #include <boost/shared_ptr.hpp>
|
|---|
| 9 |
|
|---|
| 10 | #include <settings/client/settings_client.hpp>
|
|---|
| 11 | #include <nscapi/settings_proxy.hpp>
|
|---|
| 12 | #include <nscapi/functions.hpp>
|
|---|
| 13 |
|
|---|
| 14 | #include <net/net.hpp>
|
|---|
| 15 |
|
|---|
| 16 | namespace nscapi {
|
|---|
| 17 |
|
|---|
| 18 | namespace settings_object_helper {
|
|---|
| 19 | class default_object_type {
|
|---|
| 20 | std::wstring path;
|
|---|
| 21 | std::wstring alias;
|
|---|
| 22 | std::wstring value;
|
|---|
| 23 | std::wstring parent;
|
|---|
| 24 | };
|
|---|
| 25 |
|
|---|
| 26 | template<class object_type>
|
|---|
| 27 | class default_object_reader {
|
|---|
| 28 | static void read_target(boost::shared_ptr<nscapi::settings_proxy> proxy, object_type &object) {}
|
|---|
| 29 | static void apply_parent(object_type &object, object_type &parent) {}
|
|---|
| 30 | static void post_process_object(object_type &object) {}
|
|---|
| 31 | static void init_default(object_type &object) {}
|
|---|
| 32 | };
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 | template<class object_type = default_object_type, class object_reader = default_object_reader<default_object_type> >
|
|---|
| 36 | struct target_handler : boost::noncopyable {
|
|---|
| 37 | typedef boost::optional<object_type> optional_object;
|
|---|
| 38 | typedef optional_object optarget;
|
|---|
| 39 | typedef object_type target;
|
|---|
| 40 | typedef std::map<std::wstring, object_type> object_list_type;
|
|---|
| 41 | typedef target_handler<object_type, object_reader> my_type;
|
|---|
| 42 |
|
|---|
| 43 | object_list_type object_list;
|
|---|
| 44 | object_list_type template_list;
|
|---|
| 45 |
|
|---|
| 46 | void add_missing(boost::shared_ptr<nscapi::settings_proxy> proxy, std::wstring path, std::wstring alias, std::wstring value, bool is_template = false) {
|
|---|
| 47 | if (has_object(alias))
|
|---|
| 48 | return;
|
|---|
| 49 | add(proxy, path, alias, value, is_template);
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | object_type add(boost::shared_ptr<nscapi::settings_proxy> proxy, std::wstring path, std::wstring alias, std::wstring value, bool is_template = false) {
|
|---|
| 53 | object_type object;
|
|---|
| 54 | object.alias = alias;
|
|---|
| 55 | object.value = value;
|
|---|
| 56 | object.path = path + _T("/") + alias;
|
|---|
| 57 | object.parent = _T("default");
|
|---|
| 58 |
|
|---|
| 59 | object_reader::read_target(proxy, object);
|
|---|
| 60 |
|
|---|
| 61 | if (!object.parent.empty() && object.parent != alias & object.parent != object.alias) {
|
|---|
| 62 | object_type parent;
|
|---|
| 63 | optional_object tmp = find_object(object.parent);
|
|---|
| 64 | if (!tmp) {
|
|---|
| 65 | parent = add(proxy, path, object.parent, _T(""));
|
|---|
| 66 | add_template(parent);
|
|---|
| 67 | } else {
|
|---|
| 68 | parent = *tmp;
|
|---|
| 69 | }
|
|---|
| 70 | object_reader::apply_parent(object, parent);
|
|---|
| 71 | }
|
|---|
| 72 | if (is_template)
|
|---|
| 73 | add_template(object);
|
|---|
| 74 | else
|
|---|
| 75 | add_object(object);
|
|---|
| 76 | return object;
|
|---|
| 77 | }
|
|---|
| 78 |
|
|---|
| 79 | void rebuild(boost::shared_ptr<nscapi::settings_proxy> proxy) {
|
|---|
| 80 | std::list<object_type> tmp;
|
|---|
| 81 | BOOST_FOREACH(object_list_type::value_type t, object_list) {
|
|---|
| 82 | tmp.push_back(t.second);
|
|---|
| 83 | }
|
|---|
| 84 | object_list.clear();
|
|---|
| 85 | BOOST_FOREACH(const &object_item o, tmp) {
|
|---|
| 86 | std::wstring::size_type pos = o.path.find_last_of(_T("/"));
|
|---|
| 87 | if (pos == std::wstring::npos)
|
|---|
| 88 | continue;
|
|---|
| 89 | add(proxy, o.path.substr(0, pos-1), o.path.substr(pos), o.host);
|
|---|
| 90 | }
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 |
|
|---|
| 94 | optional_object find_object(std::wstring alias) {
|
|---|
| 95 | object_list_type::const_iterator cit = object_list.find(alias);
|
|---|
| 96 | if (cit != object_list.end())
|
|---|
| 97 | return optional_object(cit->second);
|
|---|
| 98 | cit = template_list.find(alias);
|
|---|
| 99 | if (cit != template_list.end())
|
|---|
| 100 | return optional_object(cit->second);
|
|---|
| 101 | return optional_object();
|
|---|
| 102 | }
|
|---|
| 103 |
|
|---|
| 104 | bool has_object(std::wstring alias) {
|
|---|
| 105 | object_list_type::const_iterator cit = object_list.find(alias);
|
|---|
| 106 | if (cit != object_list.end())
|
|---|
| 107 | return true;
|
|---|
| 108 | cit = template_list.find(alias);
|
|---|
| 109 | if (cit != template_list.end())
|
|---|
| 110 | return true;
|
|---|
| 111 | return false;
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 |
|
|---|
| 115 | std::wstring to_wstring() {
|
|---|
| 116 | std::wstringstream ss;
|
|---|
| 117 | ss << _T("Objects: ");
|
|---|
| 118 | BOOST_FOREACH(object_list_type::value_type t, object_list) {
|
|---|
| 119 | ss << _T(", ") << t.first << _T(" = {") << t.second.to_wstring() + _T("} ");
|
|---|
| 120 | }
|
|---|
| 121 | ss << _T("Templates: ");
|
|---|
| 122 | BOOST_FOREACH(object_list_type::value_type t, template_list) {
|
|---|
| 123 | ss << _T(", ") << t.first << _T(" = {") << t.second.to_wstring() + _T("} ");
|
|---|
| 124 | }
|
|---|
| 125 | return ss.str();
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | void add_object(object_type object) {
|
|---|
| 129 | object_reader::post_process_object(object);
|
|---|
| 130 | object_list_type::iterator cit = template_list.find(object.alias);
|
|---|
| 131 | if (cit != template_list.end())
|
|---|
| 132 | template_list.erase(cit);
|
|---|
| 133 | object_list[object.alias] = object;
|
|---|
| 134 | }
|
|---|
| 135 | void add_template(object_type object) {
|
|---|
| 136 | object_list_type::const_iterator cit = object_list.find(object.alias);
|
|---|
| 137 | if (cit != object_list.end())
|
|---|
| 138 | return;
|
|---|
| 139 | object_reader::post_process_object(object);
|
|---|
| 140 | template_list[object.alias] = object;
|
|---|
| 141 | }
|
|---|
| 142 | };
|
|---|
| 143 | }
|
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 | namespace targets {
|
|---|
| 147 | struct target_object {
|
|---|
| 148 |
|
|---|
| 149 | std::wstring path;
|
|---|
| 150 | std::wstring alias;
|
|---|
| 151 | std::wstring value;
|
|---|
| 152 | std::wstring parent;
|
|---|
| 153 |
|
|---|
| 154 | net::wurl address;
|
|---|
| 155 | typedef std::map<std::wstring,std::wstring> options_type;
|
|---|
| 156 | options_type options;
|
|---|
| 157 |
|
|---|
| 158 | std::wstring to_wstring() const {
|
|---|
| 159 | std::wstringstream ss;
|
|---|
| 160 | ss << _T("Target: ") << alias;
|
|---|
| 161 | ss << _T(", address: ") << get_address();
|
|---|
| 162 | ss << _T(", parent: ") << parent;
|
|---|
| 163 | BOOST_FOREACH(options_type::value_type o, options) {
|
|---|
| 164 | ss << _T(", option[") << o.first << _T("]: ") << o.second;
|
|---|
| 165 | }
|
|---|
| 166 | return ss.str();
|
|---|
| 167 | }
|
|---|
| 168 | std::wstring get_address() const {
|
|---|
| 169 | return address.to_string();
|
|---|
| 170 | }
|
|---|
| 171 | void set_address(std::wstring value) {
|
|---|
| 172 | net::wurl n = net::parse(value);
|
|---|
| 173 | address.apply(n);
|
|---|
| 174 | }
|
|---|
| 175 | void set_host(std::wstring value) {
|
|---|
| 176 | address.host = value;
|
|---|
| 177 | }
|
|---|
| 178 | void set_port(int value) {
|
|---|
| 179 | address.host = strEx::itos(value);
|
|---|
| 180 | }
|
|---|
| 181 | bool has_option(std::wstring key) const {
|
|---|
| 182 | return options.find(key) != options.end();
|
|---|
| 183 | }
|
|---|
| 184 | bool has_option(std::string key) const {
|
|---|
| 185 | return has_option(utf8::cvt<std::wstring>(key));
|
|---|
| 186 | }
|
|---|
| 187 | void set_property_int(std::wstring key, int value) {
|
|---|
| 188 | if (key == _T("port")) {
|
|---|
| 189 | set_port(value);
|
|---|
| 190 | } else
|
|---|
| 191 | options[key] = strEx::itos(value);
|
|---|
| 192 | }
|
|---|
| 193 | void set_property_bool(std::wstring key, bool value) {
|
|---|
| 194 | options[key] = value?_T("true"):_T("false");
|
|---|
| 195 | }
|
|---|
| 196 | void set_property_string(std::wstring key, std::wstring value) {
|
|---|
| 197 | if (key == _T("host")) {
|
|---|
| 198 | set_host(value);
|
|---|
| 199 | } else
|
|---|
| 200 | options[key] = value;
|
|---|
| 201 | }
|
|---|
| 202 |
|
|---|
| 203 | nscapi::functions::destination_container to_destination_container() const {
|
|---|
| 204 | nscapi::functions::destination_container ret;
|
|---|
| 205 | if (!alias.empty())
|
|---|
| 206 | ret.id = utf8::cvt<std::string>(alias);
|
|---|
| 207 | ret.address.apply(net::wide_to_url(address));
|
|---|
| 208 | BOOST_FOREACH(const options_type::value_type &kvp, options) {
|
|---|
| 209 | ret.data[utf8::cvt<std::string>(kvp.first)] = utf8::cvt<std::string>(kvp.second);
|
|---|
| 210 | }
|
|---|
| 211 | return ret;
|
|---|
| 212 | }
|
|---|
| 213 |
|
|---|
| 214 | };
|
|---|
| 215 | typedef boost::optional<target_object> optional_target_object;
|
|---|
| 216 | typedef std::map<std::wstring,std::wstring> targets_type;
|
|---|
| 217 |
|
|---|
| 218 | struct target_object_reader {
|
|---|
| 219 | typedef target_object object_type;
|
|---|
| 220 | static void read_target(boost::shared_ptr<nscapi::settings_proxy> proxy, object_type &object);
|
|---|
| 221 | static void apply_parent(object_type &object, object_type &parent);
|
|---|
| 222 | };
|
|---|
| 223 |
|
|---|
| 224 | namespace sh = nscapi::settings_helper;
|
|---|
| 225 | struct dummy_custom_reader {
|
|---|
| 226 | typedef target_object object_type;
|
|---|
| 227 | static void add_custom_keys(sh::settings_registry &settings, boost::shared_ptr<nscapi::settings_proxy> proxy, object_type &object) {}
|
|---|
| 228 | };
|
|---|
| 229 |
|
|---|
| 230 | template<class custom_reader>
|
|---|
| 231 | struct split_object_reader {
|
|---|
| 232 | typedef target_object object_type;
|
|---|
| 233 |
|
|---|
| 234 | static void post_process_object(object_type &object) {
|
|---|
| 235 | custom_reader::post_process_target(object);
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | static void read_target(boost::shared_ptr<nscapi::settings_proxy> proxy, object_type &object) {
|
|---|
| 239 | object.address = net::parse(object.value, 0);
|
|---|
| 240 | if (object.alias == _T("default"))
|
|---|
| 241 | custom_reader::init_default(object);
|
|---|
| 242 |
|
|---|
| 243 | nscapi::settings_helper::settings_registry settings(proxy);
|
|---|
| 244 |
|
|---|
| 245 | object_type::options_type options;
|
|---|
| 246 | settings.path(object.path).add_path()
|
|---|
| 247 | (object.alias, nscapi::settings_helper::wstring_map_path(&options),
|
|---|
| 248 | _T("TARGET DEFENITION"), _T("Target definition for: ") + object.alias)
|
|---|
| 249 |
|
|---|
| 250 | ;
|
|---|
| 251 |
|
|---|
| 252 | settings.path(object.path).add_key()
|
|---|
| 253 |
|
|---|
| 254 | (_T("address"), sh::string_fun_key<std::wstring>(boost::bind(&object_type::set_address, &object, _1)),
|
|---|
| 255 | _T("TARGET ADDRESS"), _T("Target host address"))
|
|---|
| 256 |
|
|---|
| 257 | (_T("host"), sh::string_fun_key<std::wstring>(boost::bind(&object_type::set_host, &object, _1)),
|
|---|
| 258 | _T("TARGET HOST"), _T("The target server to report results to."))
|
|---|
| 259 |
|
|---|
| 260 | (_T("port"), sh::int_fun_key<int>(boost::bind(&object_type::set_port, &object, _1)),
|
|---|
| 261 | _T("TARGET PORT"), _T("The target server port"))
|
|---|
| 262 |
|
|---|
| 263 | (_T("alias"), nscapi::settings_helper::wstring_key(&object.alias, object.alias),
|
|---|
| 264 | _T("TARGET ALIAS"), _T("The alias for the target"))
|
|---|
| 265 |
|
|---|
| 266 | (_T("parent"), nscapi::settings_helper::wstring_key(&object.parent, _T("default")),
|
|---|
| 267 | _T("TARGET PARENT"), _T("The parent the target inherits from"))
|
|---|
| 268 |
|
|---|
| 269 | ;
|
|---|
| 270 | custom_reader::add_custom_keys(settings, proxy, object);
|
|---|
| 271 |
|
|---|
| 272 | settings.register_all();
|
|---|
| 273 | settings.notify();
|
|---|
| 274 |
|
|---|
| 275 | BOOST_FOREACH(const object_type::options_type::value_type &kvp, options) {
|
|---|
| 276 | if (!object.has_option(kvp.first))
|
|---|
| 277 | object.options[kvp.first] = kvp.second;
|
|---|
| 278 | }
|
|---|
| 279 |
|
|---|
| 280 | }
|
|---|
| 281 |
|
|---|
| 282 | static void apply_parent(object_type &object, object_type &parent) {
|
|---|
| 283 | object.address.import(parent.address);
|
|---|
| 284 | BOOST_FOREACH(object_type::options_type::value_type i, parent.options) {
|
|---|
| 285 | if (object.options.find(i.first) == object.options.end())
|
|---|
| 286 | object.options[i.first] = i.second;
|
|---|
| 287 | }
|
|---|
| 288 | }
|
|---|
| 289 |
|
|---|
| 290 | };
|
|---|
| 291 | template<class custom_reader>
|
|---|
| 292 | struct handler : public nscapi::settings_object_helper::target_handler<target_object, split_object_reader<custom_reader > > {};
|
|---|
| 293 |
|
|---|
| 294 | /*
|
|---|
| 295 | template<class custom_reader>
|
|---|
| 296 | */
|
|---|
| 297 | //typedef nscapi::settings_object_helper::target_handler<target_object, split_object_reader<dummy_custom_reader > > handler;
|
|---|
| 298 |
|
|---|
| 299 | }
|
|---|
| 300 | }
|
|---|
| 301 |
|
|---|