LCOV - code coverage report
Current view: top level - ugbase/registry - registry.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 35.5 % 155 55
Test Date: 2025-09-21 23:31:46 Functions: 37.0 % 27 10

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Authors: Andreas Vogel, Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <string>
      34              : 
      35              : #include "registry.h"
      36              : #include "registry_util.h"
      37              : #ifdef UG_FOR_LUA
      38              : #include "bindings/lua/lua_function_handle.h"
      39              : #endif
      40              : 
      41              : using namespace ug::bridge;
      42              : 
      43              : namespace ug{
      44              : namespace bridge
      45              : {
      46              : 
      47            1 : Registry::Registry()
      48            1 :         :m_bForceConstructionWithSmartPtr(false)
      49              : {
      50              : //      register native types as provided in ParameterStack
      51              : //      we use the c_ prefix to avoid clashes with java native types in java bindings.
      52            2 :         add_class_<bool>("c_bool");
      53            2 :         add_class_<int>("c_int");
      54            2 :         add_class_<size_t>("c_size_t");
      55            2 :         add_class_<float>("c_float");
      56            2 :         add_class_<double>("c_double");
      57            2 :         add_class_<char>("c_char");
      58            2 :         add_class_<const char*>("c_const_char_ptr");
      59            2 :         add_class_<std::string>("c_string");
      60            2 :         add_class_<void>("c_void");
      61              : #ifdef UG_FOR_LUA
      62            2 :         add_class_<LuaFunctionHandle>("c_LuaFunctionHandle");
      63              : #endif
      64            1 : }
      65              : 
      66            0 : Registry::Registry(const Registry& reg)
      67            0 :         : m_bForceConstructionWithSmartPtr(false)
      68              : {
      69            0 : }
      70              : 
      71            1 : Registry::~Registry()
      72              : {
      73              : //  delete registered functions
      74          322 :         for(size_t i = 0; i < m_vFunction.size(); ++i)
      75              :         {
      76          321 :                 if(m_vFunction[i] != NULL)
      77          321 :                         delete m_vFunction[i];
      78              :         }
      79              : //  delete registered classes
      80         1350 :         for(size_t i = 0; i < m_vClass.size(); ++i)
      81              :         {
      82         1349 :                 if(m_vClass[i] != NULL)
      83         1349 :                         delete m_vClass[i];
      84              :         }
      85              : //      delete registered class groups
      86          274 :         for(size_t i = 0; i < m_vClassGroups.size(); ++i){
      87          273 :                 delete m_vClassGroups[i];
      88              :         }
      89            1 : }
      90              : 
      91              : 
      92              : ////////////////////////
      93              : //      callbacks
      94              : ////////////////////////
      95              : 
      96            0 : void Registry::add_callback(FuncRegistryChanged callback)
      97              : {
      98            0 :         m_callbacksRegChanged.push_back(callback);
      99            0 : }
     100              : 
     101            2 : bool Registry::registry_changed()
     102              : {
     103            2 :         if(!m_callbacksRegChanged.empty())
     104            0 :                 UG_THROW("Sorry, currently no listeners can be registered at the "
     105              :                                 " the Registry due to restrictions of the VRL binding.");
     106              : 
     107              : //      iterate through all callbacks and call them
     108            2 :         for(size_t i = 0; i < m_callbacksRegChanged.size(); ++i){
     109            0 :                 m_callbacksRegChanged[i](this);
     110              :         }
     111              : 
     112              : //      ok
     113            2 :         return true;
     114              : }
     115              : 
     116              : //////////////////////
     117              : // global functions
     118              : //////////////////////
     119              : 
     120            0 : size_t Registry::num_functions() const
     121              : {
     122            0 :         return m_vFunction.size();
     123              : }
     124              : 
     125            0 : ExportedFunction& Registry::get_function(size_t ind)
     126              : {
     127            0 :         return *m_vFunction.at(ind)->get_overload(0);
     128              : }
     129              : 
     130            0 : const ExportedFunction& Registry::get_function(size_t ind) const
     131              : {
     132            0 :         return *m_vFunction.at(ind)->get_overload(0);
     133              : }
     134              : 
     135            0 : size_t Registry::num_overloads(size_t ind) const
     136              : {
     137            0 :         return m_vFunction.at(ind)->num_overloads();
     138              : }
     139              : 
     140            0 : ExportedFunction& Registry::get_overload(size_t funcInd, size_t oInd)
     141              : {
     142            0 :         return *m_vFunction.at(funcInd)->get_overload(oInd);
     143              : }
     144              : 
     145            0 : ExportedFunctionGroup& Registry::get_function_group(size_t ind)
     146              : {
     147            0 :         return *m_vFunction.at(ind);
     148              : }
     149              : 
     150              : 
     151              : ///////////////////
     152              : // classes
     153              : ///////////////////
     154              : 
     155            0 : size_t Registry::num_classes() const
     156              : {
     157            0 :         return m_vClass.size();
     158              : }
     159              : 
     160              : /// returns an exported function
     161            0 : const IExportedClass& Registry::get_class(size_t ind) const
     162              : {
     163            0 :         return *m_vClass.at(ind);
     164              : }
     165              : 
     166         4961 : IExportedClass* Registry::get_class(const std::string& name)
     167              : {
     168              : //todo: use a map to access classes by name.
     169      3459169 :         for(size_t i = 0; i < m_vClass.size(); ++i)
     170      3455472 :                 if(name == m_vClass[i]->name())
     171         1264 :                         return m_vClass[i];
     172              : 
     173              :         return NULL;
     174              : }
     175              : 
     176            0 : const IExportedClass* Registry::get_class(const std::string& name) const
     177              : {
     178              : //todo: use a map to access classes by name.
     179            0 :         for(size_t i = 0; i < m_vClass.size(); ++i)
     180            0 :                 if(name == m_vClass[i]->name())
     181            0 :                         return m_vClass[i];
     182              : 
     183              :         return NULL;
     184              : }
     185              : 
     186              : 
     187            0 : void Registry::set_force_construct_via_smart_pointer(bool bForceConstructionWithSmartPtr)
     188              : {
     189            0 :         m_bForceConstructionWithSmartPtr = bForceConstructionWithSmartPtr;
     190            0 : }
     191              : 
     192            0 : bool Registry::check_consistency()
     193              : {
     194              : 
     195              :         // list to check for duplicates in global functions.
     196              :         // comparison is not case sensitive.
     197              :         std::vector<std::string> globalFunctionNames;
     198              :     
     199              :         //      check global functions
     200              :         size_t globFctUndef = 0;
     201            0 :         for(size_t i=0; i<num_functions(); i++)
     202              :         {
     203              :                 //      get function
     204            0 :                 ExportedFunctionGroup& funcGrp = get_function_group(i);
     205              :                 
     206              :                 // add lower case name entry
     207            0 :                 globalFunctionNames.push_back(ToLower(funcGrp.name()));
     208              : 
     209              :                 //      check all overloads
     210            0 :                 for(size_t j = 0; j < funcGrp.num_overloads(); ++j){
     211            0 :                         if(!funcGrp.get_overload(j)->check_consistency())
     212            0 :                                 globFctUndef++;
     213              :                 }
     214              :         }
     215              :         
     216              :         // check for duplicate function names. comparison is not case sensitive.
     217              :         std::vector<std::string> globFuncDuplicates = 
     218            0 :                         FindDuplicates(globalFunctionNames);
     219              :         bool globFuncDuplicatesExist = !globFuncDuplicates.empty();
     220              :         //todo: use stringstream
     221            0 :         std::string duplicateFuncMsg = "#### Registry ERROR: duplicate function names:\n";
     222            0 :         if (globFuncDuplicatesExist) {
     223            0 :                 for(size_t i = 0; i < globFuncDuplicates.size();i++) {
     224            0 :                         duplicateFuncMsg+=  + "\t" + globFuncDuplicates[i] + "\n";
     225              :                 }
     226              :                 duplicateFuncMsg += "#### NOTE: it is not allowed to register multiple"
     227              :                                 " functions with equal names. Comparison is NOT case sensitive,"
     228              :                                 " e.g., 'Func' and 'func' are equal.\n\n";
     229              :         }
     230              : 
     231            0 :         set_force_construct_via_smart_pointer(false);
     232              : 
     233              : //      check classes and their methods
     234              :         size_t baseClassUndef = 0;
     235              :         size_t methodUndef = 0;
     236              :         size_t constructorUndef = 0;
     237              :         size_t notConstructedAsSmartPtr = 0;
     238              :         // list to check for duplicate classes.
     239              :         // comparison is not case sensitive.
     240              :         std::vector<std::string> classNames;
     241            0 :         for(size_t i=0; i<num_classes(); i++)
     242              :         {
     243              :         //      get class
     244            0 :                 const bridge::IExportedClass &c = get_class(i);
     245              :                 
     246              :         //      check if class is constructed via smart pointer
     247            0 :                 if(m_bForceConstructionWithSmartPtr)
     248              :                 {
     249            0 :                         if(c.is_instantiable() && !c.construct_as_smart_pointer())
     250              :                         {
     251            0 :                                 UG_ERR_LOG("#### Registry ERROR: Class " << c.name()<<" is "
     252              :                                        "instantiable, but not constructed as Smart Pointer.\n");
     253            0 :                                 notConstructedAsSmartPtr++;
     254              :                         }
     255              :                 }
     256              : 
     257              :         //      add lower case name entry
     258            0 :                 classNames.push_back(ToLower(c.name()));
     259              : 
     260              :         //      check class (e.g. that base classes have been named)
     261            0 :                 if(!c.check_consistency()){
     262            0 :                         UG_ERR_LOG("#### Registry ERROR: Base Class Error for class " << c.name()<<"\n");
     263            0 :                         baseClassUndef++;
     264              :                 }
     265              : 
     266              :         //      check methods
     267            0 :                 for(size_t j=0; j<c.num_methods(); j++)
     268            0 :                         if(!c.get_method(j).check_consistency(c.name()))
     269            0 :                                 methodUndef++;
     270              : 
     271            0 :                 for(size_t j=0; j<c.num_const_methods(); j++)
     272            0 :                         if(!c.get_const_method(j).check_consistency(c.name()))
     273            0 :                                 methodUndef++;
     274              : 
     275              :         //      check constructors
     276            0 :                 for(size_t j=0; j<c.num_constructors(); j++)
     277            0 :                         if(!c.get_constructor(j).check_consistency(c.name()))
     278            0 :                                 constructorUndef++;
     279              :         }
     280              :         
     281              :         // check for duplicate class names. comparison is not case sensitive.
     282              :         std::vector<std::string> classDuplicates = 
     283            0 :                         FindDuplicates(classNames);
     284              :         bool classDuplicatesExist = classDuplicates.size()>0;
     285              :         //todo: use stringstream
     286              :         std::string duplicateClassMsg = 
     287            0 :                                 "#### Registry ERROR: duplicate class names:\n";
     288            0 :         if (classDuplicatesExist) {
     289            0 :                 for(size_t i = 0; i < classDuplicates.size();i++) {
     290            0 :                         duplicateClassMsg+= "\t" + classDuplicates[i] + "\n";
     291              :                 }
     292              :                 duplicateClassMsg += "#### NOTE: it is not allowed to register multiple"
     293              :                                 "  classes with equal names. Comparison is NOT case sensitive,"
     294              :                                 " e.g., 'Class' and 'class' are equal.\n\n";
     295              :         }
     296              : 
     297              : //      log error messages
     298            0 :         if(globFctUndef > 0)
     299            0 :                 UG_ERR_LOG("#### Registry ERROR: "<<globFctUndef<<
     300              :                        " global Functions are using undeclared Classes.\n");
     301            0 :         if(methodUndef > 0)
     302            0 :                 UG_ERR_LOG("#### Registry ERROR: "<<methodUndef<<
     303              :                        " Methods are using undeclared Classes.\n");
     304            0 :         if(baseClassUndef > 0)
     305            0 :                 UG_ERR_LOG("#### Registry ERROR: "<<baseClassUndef<<
     306              :                        " Base-Classes are using undeclared Classes.\n");
     307            0 :         if(constructorUndef > 0)
     308            0 :                 UG_ERR_LOG("#### Registry ERROR: "<<constructorUndef<<
     309              :                        " Constructors are using undeclared Classes.\n");
     310            0 :         if(notConstructedAsSmartPtr > 0)
     311            0 :                 UG_ERR_LOG("#### Registry ERROR: "<<notConstructedAsSmartPtr<<
     312              :                        " Classes are not constructed as SmartPtr.\n");
     313            0 :         if(globFuncDuplicatesExist) {
     314              :                 UG_ERR_LOG(duplicateFuncMsg);
     315              :         }
     316            0 :         if(classDuplicatesExist) {
     317              :                 UG_ERR_LOG(duplicateClassMsg);
     318              :         }
     319              : 
     320              : //      return false if undefined classes or functions and/or duplicates have been found
     321            0 :         if(globFctUndef > 0) return false;
     322            0 :         if(methodUndef > 0) return false;
     323            0 :         if(baseClassUndef > 0) return false;
     324            0 :         if(constructorUndef > 0) return false;
     325            0 :         if(notConstructedAsSmartPtr > 0) return false;
     326            0 :         if(globFuncDuplicatesExist) return false;
     327            0 :         if(classDuplicatesExist) return false;
     328              : 
     329              : //      everything fine
     330              :         return true;
     331            0 : }
     332              : 
     333              : 
     334            0 : size_t Registry::num_class_groups() const
     335              : {
     336            0 :         return m_vClassGroups.size();
     337              : }
     338              : 
     339            0 : const ClassGroupDesc* Registry::get_class_group(size_t i) const
     340              : {
     341            0 :         return m_vClassGroups[i];
     342              : }
     343              : 
     344            0 : ClassGroupDesc* Registry::get_class_group(size_t i)
     345              : {
     346            0 :         return m_vClassGroups[i];
     347              : }
     348              : 
     349         1264 : ClassGroupDesc* Registry::get_class_group(const std::string& name)
     350              : {
     351              : //todo: use a map to quickly access classGroups by name
     352       183401 :         for(size_t i = 0; i < m_vClassGroups.size(); ++i)
     353       183128 :                 if(name == m_vClassGroups[i]->name())
     354              :                         return m_vClassGroups[i];
     355              : 
     356              : //      since we reached this point, no class-group with the given name exists.
     357              :         
     358              :         // check that name does not contain illegal characters
     359          273 :         if (!IsValidRegistryIdentifier(name)) {
     360            0 :                 UG_THROW_REGISTRY_ERROR(name,
     361              :                 "Trying add group '" << name << "' that"
     362              :                 << " contains illegal characters. "<< GetRegistryIdentifierMessage());
     363              :         }
     364              : 
     365          273 :         ClassGroupDesc* classGroup = new ClassGroupDesc();
     366              :         classGroup->set_name(name);
     367          273 :         m_vClassGroups.push_back(classGroup);
     368              : 
     369              :         return classGroup;
     370              : }
     371              : 
     372            0 : const ClassGroupDesc* Registry::get_class_group(const std::string& name) const
     373              : {
     374              : //todo: use a map to quickly access classGroups by name
     375            0 :         for(size_t i = 0; i < m_vClassGroups.size(); ++i)
     376            0 :                 if(name == m_vClassGroups[i]->name())
     377              :                         return m_vClassGroups[i];
     378              : 
     379              : //      since we reached this point, no class-group with the given name exists.
     380              :         return NULL;
     381              : }
     382              : 
     383         1264 : void Registry::add_class_to_group(std::string className, std::string groupName,
     384              :                                                                   std::string classTag)
     385              : {
     386              : //      make sure that no class with groupName exists.
     387         1264 :         if(classname_registered(groupName)){
     388            0 :                 UG_THROW_REGISTRY_ERROR(groupName,
     389              :                 "A class with the given group name '"<<groupName<<"' already exists.");
     390              :         }
     391              : 
     392         1264 :         ClassGroupDesc* groupDesc = get_class_group(groupName);
     393              : //todo: make sure that groupDesc does not already contain className.
     394         1264 :         IExportedClass* expClass = get_class(className);
     395         1264 :         if(!expClass){
     396            0 :                 UG_THROW_REGISTRY_ERROR(groupName,
     397              :                 "The given class has to be registered before "
     398              :                                                 "adding it to a group: " << className);
     399              :         }
     400              : 
     401              :         if(expClass)
     402         1264 :                 groupDesc->add_class(expClass, classTag);
     403         1264 : }
     404              : 
     405              : 
     406         3697 : bool Registry::classname_registered(const std::string& name)
     407              : {
     408         3697 :         return get_class(name) != NULL;
     409              : }
     410              : 
     411         1349 : bool Registry::groupname_registered(const std::string& name)
     412              : {
     413              : //todo: use a map to quickly access classGroups by name
     414       194526 :         for(size_t i = 0; i < m_vClassGroups.size(); ++i){
     415       193177 :                 if(name == m_vClassGroups[i]->name())
     416              :                         return true;
     417              :         }
     418              :         return false;
     419              : }
     420              : 
     421              : // returns true if functionname is already used by a function in this registry
     422            1 : bool Registry::functionname_registered(const std::string& name)
     423              : {
     424          290 :         for(size_t i = 0; i < m_vFunction.size(); ++i)
     425          289 :                 if(name == m_vFunction[i]->name())
     426              :                         return true;
     427              : 
     428              :         return false;
     429              : }
     430              : 
     431         1819 : ExportedFunctionGroup* Registry::get_exported_function_group(const std::string& name)
     432              : {
     433       405953 :         for(size_t i = 0; i < m_vFunction.size(); ++i)
     434       405632 :                 if(name == m_vFunction[i]->name())
     435              :                         return m_vFunction[i];
     436              : 
     437              :         return NULL;
     438              : }
     439              : 
     440              : }// end of namespace
     441              : }// end of namespace
        

Generated by: LCOV version 2.0-1