11#include <userver/components/component_fwd.hpp>
12#include <userver/components/static_config_validator.hpp>
14USERVER_NAMESPACE_BEGIN
23auto NameRegistrationFromComponentType() ->
decltype(std::string_view{T::kName}) {
24 return std::string_view{T::kName};
27template <
class T,
class... Args>
28auto NameRegistrationFromComponentType(Args...) {
31 "Component does not have a 'kName' member convertible to "
32 "std::string_view. You have to explicitly specify the name: "
33 "component_list.Append<T>(name)."
35 return std::string_view{};
38using ComponentBaseFactory = std::function<std::unique_ptr<
39 components::RawComponentBase>(
const components::ComponentConfig&,
const components::ComponentContext&)>;
44 const components::ComponentConfigMap& config_map,
45 const std::string& name,
46 ComponentBaseFactory factory
49class ComponentAdderBase {
51 ComponentAdderBase() =
delete;
52 ComponentAdderBase(
const ComponentAdderBase&) =
delete;
53 ComponentAdderBase(ComponentAdderBase&&) =
delete;
54 ComponentAdderBase& operator=(
const ComponentAdderBase&) =
delete;
55 ComponentAdderBase& operator=(ComponentAdderBase&&) =
delete;
57 ComponentAdderBase(std::string name, ConfigFileMode config_file_mode);
59 virtual ~ComponentAdderBase();
61 const std::string& GetComponentName()
const noexcept {
return name_; }
63 ConfigFileMode GetConfigFileMode()
const {
return config_file_mode_; }
65 virtual void operator()(Manager&,
const components::ComponentConfigMap&)
const = 0;
67 virtual void ValidateStaticConfig(
const ComponentConfig&, ValidationMode)
const = 0;
69 virtual yaml_config::Schema GetStaticConfigSchema()
const = 0;
73 ConfigFileMode config_file_mode_;
76template <
typename Component>
77class ComponentAdder
final :
public ComponentAdderBase {
79 explicit ComponentAdder(std::string name) : ComponentAdderBase(std::move(name), kConfigFileMode<Component>) {}
81 void operator()(Manager&,
const components::ComponentConfigMap&)
const override;
83 void ValidateStaticConfig(
const ComponentConfig& static_config, ValidationMode validation_mode)
const override {
84 impl::TryValidateStaticConfig<Component>(GetComponentName(), static_config, validation_mode);
87 yaml_config::Schema GetStaticConfigSchema()
const override {
return impl::GetStaticConfigSchema<Component>(); }
90template <
typename Component>
91void ComponentAdder<Component>::operator()(Manager& manager,
const components::ComponentConfigMap& config_map)
const {
95 std::is_convertible_v<Component*, components::RawComponentBase*>,
96 "Component should publicly inherit from components::ComponentBase"
97 " and the component definition should be visible at its registration"
99 impl::AddComponentImpl(
103 [](
const components::ComponentConfig& config,
const components::ComponentContext& context) {
104 return std::make_unique<Component>(config, context);
109using ComponentAdderPtr = std::unique_ptr<
const impl::ComponentAdderBase>;
111struct ComponentAdderComparator {
112 using is_transparent = std::true_type;
114 static std::string_view ToStringView(
const ComponentAdderPtr& x)
noexcept {
115 return std::string_view{x->GetComponentName()};
118 static std::string_view ToStringView(std::string_view x)
noexcept {
return x; }
120 template <
class T,
class U>
121 bool operator()(
const T& x,
const U& y)
const noexcept {
122 return ToStringView(x) < ToStringView(y);
130class ComponentList
final {
133 template <
typename Component>
134 ComponentList&
Append() &;
137 template <
typename Component>
138 ComponentList&
Append(std::string_view name) &;
147 template <
typename Component,
typename... Args>
151 bool Contains(std::string_view name)
const {
return adders_.count(name) > 0; }
154 using Adders = std::set<impl::ComponentAdderPtr, impl::ComponentAdderComparator>;
156 Adders::const_iterator begin()
const {
return adders_.begin(); }
157 Adders::const_iterator end()
const {
return adders_.end(); }
159 ComponentList& Append(impl::ComponentAdderPtr&& added) &;
168template <
typename Component>
169ComponentList& ComponentList::
Append() & {
170 return Append<Component>(impl::NameRegistrationFromComponentType<Component>());
173template <
typename Component>
174ComponentList& ComponentList::
Append(std::string_view name) & {
175 using Adder = impl::ComponentAdder<Component>;
176 auto adder = std::make_unique<
const Adder>(std::string{name});
177 return Append(std::move(adder));
180template <
typename Component,
typename... Args>
181ComponentList&& ComponentList::
Append(Args&&... args) && {
182 return std::move(Append<Component>(std::forward<Args>(args)...));