24 #ifndef FABLE_SCHEMA_FACTORY_HPP_ 25 #define FABLE_SCHEMA_FACTORY_HPP_ 32 #include <type_traits> 58 template <
typename T,
typename CRTP>
62 using MakeFunc = std::function<T(const Conf& c)>;
70 using TransformFunc = std::function<Box(Struct&&)>;
71 using FactoryMap = std::map<std::string, TypeFactory>;
72 using FactoryPairList = std::initializer_list<std::pair<std::string, TypeFactory>>;
86 :
Base<CRTP>(JsonType::object, std::move(desc)), available_(std::move(fs)) {
91 :
Base<CRTP>(JsonType::object, std::move(desc)), available_(std::move(fs)) {
102 return std::move(*dynamic_cast<CRTP*>(
this));
112 return std::move(*dynamic_cast<CRTP*>(
this));
122 return std::move(*dynamic_cast<CRTP*>(
this));
132 return std::move(*dynamic_cast<CRTP*>(
this));
143 assert(keyword !=
"");
144 factory_key_ = keyword;
187 const TypeFactory&
get_factory(
const std::string& key)
const {
return available_.at(key); }
192 bool has_factory(
const std::string& key)
const {
return available_.count(key); }
201 if (!available_.count(key)) {
202 available_.insert(std::make_pair(key, TypeFactory{std::move(s), f}));
213 if (!available_.count(key)) {
214 available_.erase(key);
216 available_.insert(std::make_pair(key, TypeFactory{std::move(s), f}));
233 template <
typename F,
234 std::enable_if_t<(std::is_default_constructible<F>::value &&
235 std::is_convertible<std::unique_ptr<F>, T>::value),
238 add_factory(key, make_prototype<F>().get_confable_schema(), [](
const Conf& c) -> T {
239 auto ptr = std::make_unique<F>();
248 if (available_.empty()) {
250 {
"description",
"no variants available"},
253 j[
"oneOf"] = factory_json_schemas();
255 this->augment_schema(j);
260 assert(schema_ !=
nullptr);
261 auto factory = c.
get<std::string>(factory_key_);
262 if (!available_.count(factory)) {
263 this->throw_error(c,
"unknown factory: {}", factory);
266 schema_->validate(c);
269 Type make(
const Conf& c)
const {
return deserialize(c); }
271 Type deserialize(
const Conf& c)
const {
272 assert(schema_ !=
nullptr);
273 auto factory = c.
get<std::string>(factory_key_);
274 if (!available_.count(factory)) {
275 this->throw_error(c,
"unknown factory: {}", factory);
280 if (args_key_ !=
"") {
281 if (c.
has(args_key_)) {
282 args = c.
at(args_key_);
286 args.
erase(factory_key_);
292 return available_.
at(factory).func(args);
295 Json serialize(
const Type& x)
const {
return x; }
298 throw std::logic_error(
"FactoryBase::from_conf() should not be used");
303 throw std::logic_error(
"FactoryBase::to_json() should not be used");
311 void reset_schema() {
312 if (available_.size() == 0) {
315 schema_.reset(
new Variant(factory_schemas()));
318 std::vector<Box> factory_schemas()
const {
319 std::vector<Box> out;
320 out.reserve(available_.size());
321 for (
auto& kv : available_) {
323 {factory_key_, make_const_str(kv.first,
"name of factory").require()},
325 if (args_key_ ==
"") {
326 base.set_properties_from(kv.second.schema);
328 base.set_property(args_key_, kv.second.schema.clone());
332 if (transform_func_) {
333 out.emplace_back(transform_func_(std::move(base)));
335 out.emplace_back(std::move(base));
341 std::vector<Json> factory_json_schemas()
const {
342 auto schemas = factory_schemas();
343 std::vector<Json> out;
344 out.reserve(schemas.size());
345 for (
auto& s : schemas) {
346 out.emplace_back(s.json_schema());
352 std::shared_ptr<Variant> schema_;
353 TransformFunc transform_func_;
354 FactoryMap available_;
355 std::string factory_key_{
"factory"};
356 std::string args_key_{
"args"};
357 bool args_subset_{
true};
364 template <
typename T>
374 template <
typename T>
388 Factory(Type* ptr, std::string&& desc, FactoryMap&& fs)
390 for (
auto&& f : fs) {
391 this->available_.insert(f);
393 this->reset_schema();
396 Factory(Type* ptr, std::string&& desc, FactoryPairList fs)
398 for (
auto&& f : fs) {
399 this->available_.insert(f);
401 this->reset_schema();
406 assert(ptr_ !=
nullptr);
407 *ptr_ = this->deserialize(c);
411 assert(ptr_ !=
nullptr);
412 j = this->serialize(*ptr_);
424 #endif // FABLE_SCHEMA_FACTORY_HPP_
void validate(const Conf &c) const override
Definition: factory.hpp:259
void from_conf(const Conf &c) override
Definition: factory.hpp:405
void add_default_factory(const std::string &key)
Definition: factory.hpp:237
void set_args_key(const std::string &keyword)
Definition: factory.hpp:157
CRTP args_key(const std::string &keyword) &&
Definition: factory.hpp:110
Definition: interface.hpp:263
CRTP args_subset(bool value) &&
Definition: factory.hpp:120
Definition: factory.hpp:59
void set_transform_schema(TransformFunc f)
Definition: factory.hpp:182
T get() const
Definition: conf.hpp:164
Definition: factory.hpp:365
CRTP transform_schema(TransformFunc f) &&
Definition: factory.hpp:130
void from_conf(const Conf &c) override
Definition: factory.hpp:297
bool has_factory(const std::string &key) const
Definition: factory.hpp:192
nlohmann::json Json
Definition: json.hpp:62
void reset_ptr() override
Definition: interface.hpp:343
bool has(const std::string &key) const
Definition: conf.hpp:130
size_t erase(const std::string &key)
Definition: conf.cpp:74
void reset_ptr() override
Definition: factory.hpp:306
Json::value_t JsonType
Definition: json.hpp:78
void set_factory_key(const std::string &keyword)
Definition: factory.hpp:142
const TypeFactory & get_factory(const std::string &key) const
Definition: factory.hpp:187
void set_factory(const std::string &key, Box &&s, MakeFunc f)
Definition: factory.hpp:212
void set_args_subset(bool value)
Definition: factory.hpp:173
Json json_schema() const override
Definition: factory.hpp:246
virtual Json to_json() const
Definition: interface.hpp:220
Conf at(const std::string &key) const
Definition: conf.cpp:58
void reset_ptr() override
Definition: factory.hpp:415
Definition: struct.hpp:73
bool add_factory(const std::string &key, Box &&s, MakeFunc f)
Definition: factory.hpp:200
Definition: variant.hpp:59
void to_json(Json &j) const override
Definition: factory.hpp:302
Definition: factory.hpp:63
Definition: interface.hpp:354
void to_json(Json &j) const override
Definition: factory.hpp:410
CRTP factory_key(const std::string &keyword) &&
Definition: factory.hpp:100
Definition: factory.hpp:375
FactoryBase(std::string &&desc="")
Definition: factory.hpp:83