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;
 
   68  virtual yaml_config::Schema GetStaticConfigSchema() 
const = 0;
 
   75template <
typename Component>
 
   76class ComponentAdder 
final : 
public ComponentAdderBase {
 
   78  explicit ComponentAdder(std::string name)
 
   79      : ComponentAdderBase(std::move(name), kConfigFileMode<Component>) {}
 
   81  void operator()(Manager&,
 
   82                  const components::ComponentConfigMap&) 
const override;
 
   84  void ValidateStaticConfig(
const ComponentConfig& static_config,
 
   85                            ValidationMode validation_mode) 
const override {
 
   86    impl::TryValidateStaticConfig<Component>(static_config, validation_mode);
 
   89  yaml_config::Schema GetStaticConfigSchema() 
const override {
 
   90    return impl::GetStaticConfigSchema<Component>();
 
   94template <
typename Component>
 
   95void ComponentAdder<Component>::operator()(
 
   96    Manager& manager, 
const components::ComponentConfigMap& config_map) 
const {
 
  100      std::is_convertible_v<Component*, 
components::impl::ComponentBase*>,
 
  101      "Component should publicly inherit from components::LoggableComponentBase" 
  102      " and the component definition should be visible at its registration");
 
  103  impl::AddComponentImpl(manager, config_map, GetComponentName(),
 
  104                         [](
const components::ComponentConfig& config,
 
  105                            const components::ComponentContext& context) {
 
  106                           return std::make_unique<Component>(config, context);
 
  110using ComponentAdderPtr = std::unique_ptr<
const impl::ComponentAdderBase>;
 
  112struct ComponentAdderComparator {
 
  113  using is_transparent = std::true_type;
 
  115  static std::string_view ToStringView(
const ComponentAdderPtr& x) 
noexcept {
 
  116    return std::string_view{x->GetComponentName()};
 
  119  static std::string_view ToStringView(std::string_view x) 
noexcept {
 
  123  template <
class T, 
class U>
 
  124  bool operator()(
const T& x, 
const U& y) 
const noexcept {
 
  125    return ToStringView(x) < ToStringView(y);
 
  133class ComponentList 
final {
 
  136  template <
typename Component>
 
  137  ComponentList& 
Append() &;
 
  140  template <
typename Component>
 
  141  ComponentList& 
Append(std::string name) &;
 
  150  template <
typename Component, 
typename... Args>
 
  154  bool Contains(std::string_view name) 
const { 
return adders_.count(name) > 0; }
 
  158      std::set<impl::ComponentAdderPtr, impl::ComponentAdderComparator>;
 
  160  Adders::const_iterator begin() 
const { 
return adders_.begin(); }
 
  161  Adders::const_iterator end() 
const { 
return adders_.end(); }
 
  163  ComponentList& Append(impl::ComponentAdderPtr&& added) &;
 
  172template <
typename Component>
 
  173ComponentList& ComponentList::
Append() & {
 
  174  return Append<Component>(
 
  175      impl::NameRegistrationFromComponentType<Component>());
 
  178template <
typename Component>
 
  179ComponentList& ComponentList::
Append(std::string name) & {
 
  180  using Adder = impl::ComponentAdder<Component>;
 
  181  auto adder = std::make_unique<
const Adder>(std::move(name));
 
  182  return Append(std::move(adder));
 
  185template <
typename Component, 
typename... Args>
 
  186ComponentList&& ComponentList::
Append(Args&&... args) && {
 
  187  return std::move(Append<Component>(std::forward<Args>(args)...));