13#include <userver/compiler/demangle.hpp> 
   14#include <userver/components/component_fwd.hpp> 
   15#include <userver/components/impl/component_base.hpp> 
   16#include <userver/engine/task/task_processor_fwd.hpp> 
   18USERVER_NAMESPACE_BEGIN
 
   20namespace engine::impl {
 
   27class ComponentContext;
 
   31enum class ComponentLifetimeStage;
 
   33class ComponentContextImpl;
 
   35using ComponentFactory =
 
   36    std::function<std::unique_ptr<components::impl::ComponentBase>(
 
   37        const components::ComponentContext&)>;
 
   40constexpr auto NameFromComponentType() -> 
decltype(std::string_view{T::kName}) {
 
   44template <
class T, 
class... Args>
 
   45constexpr auto NameFromComponentType(Args...) {
 
   46  static_assert(!
sizeof(T),
 
   47                "Component does not have a 'kName' member convertible to " 
   48                "std::string_view. You have to explicitly specify the name: " 
   49                "context.FindComponent<T>(name) or " 
   50                "context.FindComponentOptional<T>(name).");
 
   51  return std::string_view{};
 
   60  ComponentsLoadCancelledException();
 
   61  explicit ComponentsLoadCancelledException(
const std::string& message);
 
   73class ComponentContext 
final {
 
   88    return FindComponent<T>(impl::NameFromComponentType<T>());
 
   93  T& FindComponent(std::string_view name) 
const {
 
   94    if (!Contains(name)) {
 
   95      ThrowNonRegisteredComponent(name, compiler::GetTypeName<T>());
 
   98    auto* component_base = DoFindComponent(name);
 
   99    T* ptr = 
dynamic_cast<T*>(component_base);
 
  101      ThrowComponentTypeMismatch(name, compiler::GetTypeName<T>(),
 
  108  template <
typename T>
 
  109  T& FindComponent(std::string_view  = {}) {
 
  110    return ReportMisuse<T>();
 
  115  template <
typename T>
 
  117    return FindComponentOptional<T>(impl::NameFromComponentType<T>());
 
  121  template <
typename T>
 
  122  T* FindComponentOptional(std::string_view name) 
const {
 
  123    if (!Contains(name)) {
 
  126    return dynamic_cast<T*>(DoFindComponent(name));
 
  129  template <
typename T>
 
  130  T& FindComponentOptional(std::string_view  = {}) {
 
  131    return ReportMisuse<T>();
 
  137  template <
typename T>
 
  138  engine::TaskProcessor& GetTaskProcessor(
const T&) {
 
  139    return ReportMisuse<T>();
 
  142  const Manager& GetManager() 
const;
 
  147  bool Contains(std::string_view name) 
const noexcept;
 
  149  template <
typename T>
 
  150  bool Contains(
const T&) {
 
  151    return ReportMisuse<T>();
 
  155  decltype(
auto) ReportMisuse() {
 
  156    static_assert(!
sizeof(T),
 
  157                  "components::ComponentContext should be accepted by " 
  158                  "a constant reference, i.e. " 
  159                  "`MyComponent(const components::ComponentConfig& config, " 
  160                  "const components::ComponentContext& context)`");
 
  164  friend class Manager;
 
  167  ComponentContext() 
noexcept;
 
  169  void Emplace(
const Manager& manager,
 
  170               std::vector<std::string>&& loading_component_names);
 
  172  void Reset() 
noexcept;
 
  176  impl::ComponentBase* AddComponent(std::string_view name,
 
  177                                    const impl::ComponentFactory& factory);
 
  179  void OnAllComponentsLoaded();
 
  181  void OnAllComponentsAreStopping();
 
  183  void ClearComponents();
 
  185  void CancelComponentsLoad();
 
  187  [[noreturn]] 
void ThrowNonRegisteredComponent(std::string_view name,
 
  188                                                std::string_view type) 
const;
 
  189  [[noreturn]] 
void ThrowComponentTypeMismatch(
 
  190      std::string_view name, std::string_view type,
 
  191      impl::ComponentBase* component) 
const;
 
  193  impl::ComponentBase* DoFindComponent(std::string_view name) 
const;
 
  195  std::unique_ptr<impl::ComponentContextImpl> impl_;