LCOV - code coverage report
Current view: top level - include/controls - WebServerControlTypeRegistry.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 28 34 82.4 %
Date: 2025-09-03 20:01:23 Functions: 42 47 89.4 %
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 <string>
      13             : #include <map>
      14             : #include <type_traits>
      15             : #include <typeindex>
      16             : 
      17             : #include "MooseError.h"
      18             : #include "MooseUtils.h"
      19             : 
      20             : #include "minijson/minijson.h"
      21             : 
      22             : class WebServerControl;
      23             : 
      24             : namespace Moose
      25             : {
      26             : /**
      27             :  * A static registry used to register and build values of different types for the WebServerControl
      28             :  *
      29             :  * Needed due to the complexities of parsing parameter types from generic JSON received
      30             :  * by the web server.
      31             :  */
      32             : class WebServerControlTypeRegistry
      33             : {
      34             : public:
      35             :   /**
      36             :    * @return The WebServerControlTypeRegistry singleton
      37             :    */
      38             :   static WebServerControlTypeRegistry & getRegistry();
      39             : 
      40             :   /**
      41             :    * The base class for a value that is produced by this registry.
      42             :    */
      43             :   class ValueBase
      44             :   {
      45             :   public:
      46             :     /**
      47             :      * Constructor.
      48             :      * @param name The name that the value is for (typically a controllable path)
      49             :      * @param type The string representationg of the type
      50             :      */
      51         190 :     ValueBase(const std::string & name, const std::string & type) : _name(name), _type(type) {}
      52         190 :     virtual ~ValueBase() {}
      53             : 
      54             :     /**
      55             :      * @return The name that the value is for
      56             :      */
      57         318 :     const std::string & name() const { return _name; }
      58             :     /**
      59             :      * @return The string representation of the type
      60             :      */
      61         128 :     const std::string & type() const { return _type; }
      62             : 
      63             :     /**
      64             :      * Sets the controllable value given the name and type via the controllable
      65             :      * interface in \p control.
      66             :      *
      67             :      * Will broadcast the value for setting it.
      68             :      */
      69             :     virtual void setControllableValue(WebServerControl & control) = 0;
      70             : 
      71             :     /**
      72             :      * Common exception for parsing related errors in converting JSON to a value.
      73             :      */
      74             :     struct Exception : public std::exception
      75             :     {
      76             :     public:
      77           0 :       Exception(const std::string & message) : _message(message) {}
      78           0 :       virtual const char * what() const noexcept override final { return _message.c_str(); }
      79             : 
      80             :     private:
      81             :       const std::string _message;
      82             :     };
      83             : 
      84             :   private:
      85             :     /// The name that the value is for
      86             :     const std::string _name;
      87             :     /// The string representation of the type
      88             :     const std::string _type;
      89             :   };
      90             : 
      91             :   /**
      92             :    * Registers a type with string name \p type_name and the given derived type.
      93             :    */
      94             :   template <typename DerivedValueType>
      95      447224 :   static char add(const std::string & type_name)
      96             :   {
      97             :     static_assert(std::is_base_of_v<ValueBase, DerivedValueType>, "Is not derived from ValueBase");
      98             :     using value_type = typename DerivedValueType::value_type;
      99      447224 :     static const std::type_index index = typeid(value_type);
     100      447224 :     if (!getRegistry()
     101      894448 :              ._name_map.emplace(type_name, std::make_unique<Type<DerivedValueType>>(type_name))
     102      447224 :              .second)
     103           0 :       ::mooseError("WebServerControlTypeRegistry: The string type \"",
     104             :                    type_name,
     105             :                    "\" is already registered.");
     106      447224 :     if (!getRegistry()._value_types.insert(index).second)
     107           0 :       ::mooseError("WebServerControlRegistry: The type \"",
     108             :                    MooseUtils::prettyCppType<value_type>(),
     109             :                    "\" is already registered");
     110      447224 :     return 0;
     111             :   }
     112             : 
     113             :   /**
     114             :    * @return Whether or not the type \p type is registered.
     115             :    */
     116         128 :   static bool isRegistered(const std::string & type) { return getRegistry()._name_map.count(type); }
     117             : 
     118             :   /**
     119             :    * Builds a value with the type \p type, name \p name, and a default value.
     120             :    */
     121          62 :   static std::unique_ptr<ValueBase> build(const std::string & type, const std::string & name)
     122             :   {
     123          62 :     return get(type).build(name);
     124             :   }
     125             :   /**
     126             :    * Builds a value with the type \p type, name \p name, and a value parsed from \p json_value.
     127             :    *
     128             :    * Will throw ValueBase::Exception on a parsing error.
     129             :    */
     130             :   static std::unique_ptr<ValueBase>
     131         128 :   build(const std::string & type, const std::string & name, const miniJson::Json & json_value)
     132             :   {
     133         128 :     return get(type).build(name, json_value);
     134             :   }
     135             : 
     136             : private:
     137             :   /**
     138             :    * Base registry class for a type that is used to build values.
     139             :    */
     140             :   class TypeBase
     141             :   {
     142             :   public:
     143      447224 :     TypeBase(const std::string & type) : _type(type) {}
     144           0 :     virtual ~TypeBase() {}
     145             : 
     146             :     /**
     147             :      * @return The string representation of the type
     148             :      */
     149         190 :     const std::string & type() const { return _type; }
     150             :     /**
     151             :      * Builds a value with the given type, name \p name, and JSON value \p json_value.
     152             :      *
     153             :      * This will parse the JSON value into the underlying type and will be called
     154             :      * on only rank 0 where server listens.
     155             :      */
     156             :     virtual std::unique_ptr<ValueBase> build(const std::string & name,
     157             :                                              const miniJson::Json & json_value) const = 0;
     158             :     /**
     159             :      * Builds a value with the given type, name \p name, and a default value.
     160             :      *
     161             :      * This will be called on processors that are not rank 0 for cloning.
     162             :      */
     163             :     virtual std::unique_ptr<ValueBase> build(const std::string & name) const = 0;
     164             : 
     165             :   private:
     166             :     /// The string representation of the underlying type
     167             :     const std::string _type;
     168             :   };
     169             : 
     170             :   template <class DerivedValueType>
     171             :   struct Type : public TypeBase
     172             :   {
     173      447224 :     Type(const std::string & type) : TypeBase(type) {}
     174             : 
     175             :     using value_type = typename DerivedValueType::value_type;
     176             : 
     177          62 :     virtual std::unique_ptr<ValueBase> build(const std::string & name) const override final
     178             :     {
     179          62 :       return std::make_unique<DerivedValueType>(name, type());
     180             :     }
     181         128 :     virtual std::unique_ptr<ValueBase> build(const std::string & name,
     182             :                                              const miniJson::Json & json_value) const override final
     183             :     {
     184         128 :       return std::make_unique<DerivedValueType>(name, type(), json_value);
     185             :     }
     186             :   };
     187             : 
     188             :   /**
     189             :    * Internal getter for the registration object for type \p type.
     190             :    */
     191         190 :   static const TypeBase & get(const std::string & type)
     192             :   {
     193         190 :     auto & registry = getRegistry();
     194         190 :     const auto it = registry._name_map.find(type);
     195         190 :     if (it == registry._name_map.end())
     196           0 :       mooseError("WebServerControlTypeRegistry: The type '", type, "' is not registered");
     197         380 :     return *it->second;
     198             :   }
     199             : 
     200             :   /// The registration data
     201             :   std::map<std::string, std::unique_ptr<TypeBase>> _name_map;
     202             :   /// The registered value types, to avoid registering the same underlying
     203             :   /// value type multiple times
     204             :   std::set<std::type_index> _value_types;
     205             : };
     206             : }

Generated by: LCOV version 1.14