11#include <userver/components/component_fwd.hpp>
12#include <userver/components/static_config_validator.hpp>
14USERVER_NAMESPACE_BEGIN
23auto NameRegistrationFromComponentType() ->
decltype(std::string{T::kName}) {
24 return std::string{T::kName};
27template <
class T,
class... Args>
28auto NameRegistrationFromComponentType(Args...) {
29 static_assert(!
sizeof(T),
30 "Component does not have a 'kName' member convertible to "
31 "std::string. You have to explicitly specify the name: "
32 "component_list.Append<T>(name).");
36using ComponentBaseFactory =
37 std::function<std::unique_ptr<components::impl::ComponentBase>(
38 const components::ComponentConfig&,
39 const components::ComponentContext&)>;
42void AddComponentImpl(Manager& manager,
43 const components::ComponentConfigMap& config_map,
44 const std::string& name, ComponentBaseFactory factory);
46class ComponentAdderBase {
48 ComponentAdderBase() =
delete;
49 ComponentAdderBase(
const ComponentAdderBase&) =
delete;
50 ComponentAdderBase(ComponentAdderBase&&) =
delete;
51 ComponentAdderBase& operator=(
const ComponentAdderBase&) =
delete;
52 ComponentAdderBase& operator=(ComponentAdderBase&&) =
delete;
54 ComponentAdderBase(std::string name,
ConfigFileMode config_file_mode);
56 virtual ~ComponentAdderBase();
58 const std::string& GetComponentName()
const noexcept {
return name_; }
60 ConfigFileMode GetConfigFileMode()
const {
return config_file_mode_; }
62 virtual void operator()(Manager&,
63 const components::ComponentConfigMap&)
const = 0;
65 virtual void ValidateStaticConfig(
const ComponentConfig&,
66 ValidationMode)
const = 0;
73template <
typename Component>
74class ComponentAdder
final :
public ComponentAdderBase {
76 explicit ComponentAdder(std::string name)
77 : ComponentAdderBase(std::move(name), kConfigFileMode<Component>) {}
79 void operator()(Manager&,
80 const components::ComponentConfigMap&)
const override;
82 void ValidateStaticConfig(
const ComponentConfig& static_config,
83 ValidationMode validation_mode)
const override {
84 impl::TryValidateStaticConfig<Component>(static_config, validation_mode);
88template <
typename Component>
89void ComponentAdder<Component>::operator()(
90 Manager& manager,
const components::ComponentConfigMap& config_map)
const {
94 std::is_convertible_v<Component*,
components::impl::ComponentBase*>,
95 "Component should publicly inherit from components::LoggableComponentBase"
96 " and the component definition should be visible at its registration");
97 impl::AddComponentImpl(manager, config_map, GetComponentName(),
98 [](
const components::ComponentConfig& config,
99 const components::ComponentContext& context) {
100 return std::make_unique<Component>(config, context);
104using ComponentAdderPtr = std::unique_ptr<
const impl::ComponentAdderBase>;
106struct ComponentAdderComparator {
107 using is_transparent = std::true_type;
109 static std::string_view ToStringView(
const ComponentAdderPtr& x)
noexcept {
110 return std::string_view{x->GetComponentName()};
113 static std::string_view ToStringView(std::string_view x)
noexcept {
117 template <
class T,
class U>
118 bool operator()(
const T& x,
const U& y)
const noexcept {
119 return ToStringView(x) < ToStringView(y);
127class ComponentList
final {
130 template <
typename Component>
134 template <
typename Component>
135 ComponentList&
Append(std::string name) &;
144 template <
typename Component,
typename... Args>
148 bool Contains(std::string_view name)
const {
return adders_.count(name) > 0; }
152 std::set<impl::ComponentAdderPtr, impl::ComponentAdderComparator>;
154 Adders::const_iterator begin()
const {
return adders_.begin(); }
155 Adders::const_iterator end()
const {
return adders_.end(); }
157 ComponentList& Append(impl::ComponentAdderPtr&& added) &;
164template <
typename Component>
165ComponentList& ComponentList::
Append() & {
166 return Append<Component>(
167 impl::NameRegistrationFromComponentType<Component>());
170template <
typename Component>
171ComponentList& ComponentList::
Append(std::string name) & {
172 using Adder = impl::ComponentAdder<Component>;
173 auto adder = std::make_unique<
const Adder>(std::move(name));
174 return Append(std::move(adder));
177template <
typename Component,
typename... Args>
178ComponentList&& ComponentList::
Append(Args&&... args) && {
179 return std::move(Append<Component>(std::forward<Args>(args)...));