LCOV - code coverage report
Current view: top level - include/controls - WebServerControlTypeRegistry.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: d8769b Lines: 19 22 86.4 %
Date: 2025-11-07 20:01:30 Functions: 36 39 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include <functional>
      13             : #include <string>
      14             : #include <map>
      15             : #include <type_traits>
      16             : #include <typeindex>
      17             : 
      18             : #include "nlohmann/json.h"
      19             : 
      20             : #include "MooseError.h"
      21             : #include "MooseUtils.h"
      22             : 
      23             : class WebServerControl;
      24             : 
      25             : namespace Moose
      26             : {
      27             : /**
      28             :  * A static registry used to register and build values of different types for the WebServerControl
      29             :  *
      30             :  * Needed due to the complexities of parsing parameter types from generic JSON received
      31             :  * by the web server.
      32             :  */
      33             : class WebServerControlTypeRegistry
      34             : {
      35             : public:
      36             :   /**
      37             :    * @return The WebServerControlTypeRegistry singleton
      38             :    */
      39             :   static WebServerControlTypeRegistry & getRegistry();
      40             : 
      41             :   /**
      42             :    * The base class for a value that is produced by this registry.
      43             :    */
      44             :   class ControlledValueBase
      45             :   {
      46             :   public:
      47             :     /**
      48             :      * Constructor.
      49             :      * @param name The name that the value is for (typically a controllable path)
      50             :      * @param type The string representationg of the type
      51             :      */
      52             :     ControlledValueBase(const std::string & name, const std::string & type);
      53             : 
      54         190 :     virtual ~ControlledValueBase() {}
      55             : 
      56             :     /**
      57             :      * @return The name that the value is for
      58             :      */
      59         318 :     const std::string & name() const { return _name; }
      60             :     /**
      61             :      * @return The string representation of the type
      62             :      */
      63         128 :     const std::string & type() const { return _type; }
      64             : 
      65             :     /**
      66             :      * Sets the controllable value given the name and type via the controllable
      67             :      * interface in \p control.
      68             :      *
      69             :      * Will broadcast the value and set it in the derived, type-aware class.
      70             :      */
      71             :     virtual void setControllableValue(WebServerControl & control) = 0;
      72             : 
      73             :   private:
      74             :     /// The name that the value is for
      75             :     const std::string _name;
      76             :     /// The string representation of the type
      77             :     const std::string _type;
      78             :   };
      79             : 
      80             :   /**
      81             :    * Base registry class for a type that is used to build values.
      82             :    */
      83             :   class RegisteredTypeBase
      84             :   {
      85             :   public:
      86             :     RegisteredTypeBase(const std::string & type);
      87             : 
      88           0 :     virtual ~RegisteredTypeBase() {}
      89             : 
      90             :     /**
      91             :      * @return The string representation of the type
      92             :      */
      93         190 :     const std::string & type() const { return _type; }
      94             :     /**
      95             :      * Builds a value with the given type, name \p name, and JSON value \p json_value.
      96             :      *
      97             :      * This will be called on receipt of a controllable value on rank 0 in the
      98             :      * WebServerControl. It will at that point parse the value from JSON and store it.
      99             :      * Later on during sync, it will be used to broadcast the value and then locally
     100             :      * set it.
     101             :      */
     102             :     virtual std::unique_ptr<ControlledValueBase> build(const std::string & name,
     103             :                                                        const nlohmann::json & json_value) const = 0;
     104             :     /**
     105             :      * Builds a value with the given type, name \p name, and a default value.
     106             :      *
     107             :      * This will be called by the WebServerControl on ranks that are not rank 0.
     108             :      * It will be used during the sync step, where the value is broadcasted to the
     109             :      * rest of the ranks and then set locally.
     110             :      */
     111             :     virtual std::unique_ptr<ControlledValueBase> build(const std::string & name) const = 0;
     112             : 
     113             :   private:
     114             :     /// The string representation of the underlying type
     115             :     const std::string _type;
     116             :   };
     117             : 
     118             :   /**
     119             :    * Derived registry item.
     120             :    *
     121             :    * Stores how to build the value and how to parse the value from JSON.
     122             :    *
     123             :    * @tparam ControlledValue The derived ControlledValueBase class that contains
     124             :    * the implementation for setting the controllable value
     125             :    * @tparam ValueType The underlying type of the value to be controlled
     126             :    */
     127             :   template <class ControlledValue, class ValueType>
     128             :   struct RegisteredType : public RegisteredTypeBase
     129             :   {
     130      458768 :     RegisteredType(const std::string & type,
     131             :                    std::function<ValueType(const nlohmann::json &)> && parse_function)
     132      458768 :       : RegisteredTypeBase(type), _parse_function(parse_function)
     133             :     {
     134      458768 :     }
     135             : 
     136             :     virtual std::unique_ptr<ControlledValueBase>
     137          62 :     build(const std::string & name) const override final
     138             :     {
     139          62 :       return std::make_unique<ControlledValue>(name, type());
     140             :     }
     141             :     virtual std::unique_ptr<ControlledValueBase>
     142         148 :     build(const std::string & name, const nlohmann::json & json_value) const override final
     143             :     {
     144         148 :       return std::make_unique<ControlledValue>(name, type(), _parse_function(json_value));
     145             :     }
     146             : 
     147             :   private:
     148             :     /// Function that converts from json -> the value for the ValueType
     149             :     const std::function<ValueType(const nlohmann::json &)> _parse_function;
     150             :   };
     151             : 
     152             :   /**
     153             :    * Register a type in the registry
     154             :    *
     155             :    * @tparam ControlledValue The derived ControlledValueBase class that contains
     156             :    * the implementation for setting the controllable value
     157             :    * @tparam ValueType The underlying type of the value to be controlled
     158             :    * @param type_name Human readable name for the type of the value to be controlled
     159             :    * @param parse_function Function used to parse the value from JSON
     160             :    */
     161             :   template <class ControlledValue, class ValueType>
     162             :   static char add(const std::string & type_name,
     163             :                   std::function<ValueType(const nlohmann::json &)> && parse_function);
     164             : 
     165             :   /**
     166             :    * Query the registration for the given type.
     167             :    */
     168             :   static const RegisteredTypeBase * query(const std::string & type);
     169             : 
     170             :   /**
     171             :    * Get the registration for the given type, erroring if it isn't registered.
     172             :    */
     173             :   static const RegisteredTypeBase & get(const std::string & type);
     174             : 
     175             : private:
     176             :   /// The registration data
     177             :   std::map<std::string, std::unique_ptr<RegisteredTypeBase>> _name_map;
     178             :   /// The registered value types, to avoid registering the same underlying
     179             :   /// value type multiple times
     180             :   std::set<std::type_index> _value_types;
     181             : };
     182             : 
     183             : template <class ControlledValue, class ValueType>
     184             : char
     185      458768 : WebServerControlTypeRegistry::add(
     186             :     const std::string & type_name,
     187             :     std::function<ValueType(const nlohmann::json &)> && parse_function)
     188             : {
     189             :   static_assert(std::is_base_of_v<ControlledValueBase, ControlledValue>,
     190             :                 "Is not derived from ControlledValueBase");
     191             :   static_assert(std::is_same_v<typename ControlledValue::value_type, ValueType>, "Is not the same");
     192             : 
     193      458768 :   auto entry = std::make_unique<RegisteredType<ControlledValue, ValueType>>(
     194      458768 :       type_name, std::move(parse_function));
     195      458768 :   if (!getRegistry()._name_map.emplace(type_name, std::move(entry)).second)
     196           0 :     ::mooseError(
     197             :         "WebServerControlTypeRegistry: The string type \"", type_name, "\" is already registered.");
     198             : 
     199      458768 :   static const std::type_index index = typeid(ValueType);
     200      458768 :   if (!getRegistry()._value_types.insert(index).second)
     201           0 :     ::mooseError("WebServerControlRegistry: The type \"",
     202             :                  MooseUtils::prettyCppType<ValueType>(),
     203             :                  "\" is already registered");
     204      458768 :   return 0;
     205      458768 : }
     206             : }

Generated by: LCOV version 1.14