<commit_before>//=================================================================================================
// Copyright (c) 2015, <NAME>, TU Darmstadt
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Simulation, Systems Optimization and Robotics
//       group, TU Darmstadt nor the names of its contributors may be used to
//       endorse or promote products derived from this software without
//       specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//=================================================================================================

#ifndef VIGIR_PLUGINLIB_PLUGIN_MANAGER_H__
#define VIGIR_PLUGINLIB_PLUGIN_MANAGER_H__

#include <ros/ros.h>

#include <actionlib/server/simple_action_server.h>

#include <boost/noncopyable.hpp>

#include <vigir_generic_params/parameter_manager.h>

#include <vigir_pluginlib/plugin_loader.h>
#include <vigir_pluginlib/plugin.h>

#include <vigir_pluginlib_msgs/pluginlib_msgs.h>



namespace vigir_pluginlib
{
typedef actionlib::SimpleActionServer<msgs::GetPluginDescriptionsAction>  GetPluginDescriptionsActionServer;
typedef actionlib::SimpleActionServer<msgs::GetPluginStatesAction>        GetPluginStatesActionServer;
typedef actionlib::SimpleActionServer<msgs::PluginManagementAction>       PluginManagementActionServer;

class PluginManager
  : boost::noncopyable
{
protected:
  PluginManager();

public:
  typedef std::vector<PluginLoaderBase*> PluginLoaderVector;

  ~PluginManager();

  /**
   * @brief Initialize all rostopic/-services within the namespace of the given nodehandle
   * @param nh The nodehandle which is used to setup all topics/services
   */
  static void initialize(ros::NodeHandle& nh);

  /**
   * @brief Tries to extract plugin description from param server using the given name
   * @param name Name of the plugin
   * @param plugin_description Output of extracted plugin description
   * @return True if extraction was successful
   */
  static bool autocompletePluginDescriptionByName(const std::string& name, msgs::PluginDescription& plugin_description);

  /**
   * @brief Adds ClassLoader for a specific type of plugins
   * @param package The package containing the base class
   * @param base_class The type of the base class for classes to be loaded
   * @param attrib_name The attribute to search for in manifext.xml files, defaults to "plugin"
   * @param plugin_xml_paths The list of paths of plugin.xml files, defaults to be crawled via ros::package::getPlugins()
   * @exception pluginlib::LibraryLoadException Thrown if package manifest cannot be found
   */
  template<class PluginBaseClass>
  static bool addPluginClassLoader(const std::string& package, const std::string& base_class, const std::string& attrib_name = std::string("plugin"), const std::vector<std::string>& plugin_xml_paths = std::vector<std::string>())
  {
    // check for duplicate
    for (PluginLoaderBase* loader : Instance()->class_loader)
    {
      if (loader->getBaseClassType() == base_class)
      {
        ROS_DEBUG("[PluginManager] The ClassLoader for plugins of type '%s' has been already added!", base_class.c_str());
        return false;
      }
    }

    try
    {
      PluginLoader<PluginBaseClass>* loader = new PluginLoader<PluginBaseClass>(package, base_class, attrib_name, plugin_xml_paths);
      Instance()->class_loader.push_back(loader);
      ROS_INFO("[PluginManager] Added ClassLoader for plugins of type '%s'.", base_class.c_str());
      ROS_DEBUG("  Declared classes:");
      for (const std::string s : loader->getDeclaredClasses())
        ROS_DEBUG("    %s", s.c_str());
      ROS_DEBUG("  Registered libraries:");
      for (const std::string s : loader->getRegisteredLibraries())
        ROS_DEBUG("    %s", s.c_str());
    }
    catch (pluginlib::LibraryLoadException& e)
    {
      ROS_ERROR("[PluginManager] The ClassLoader for plugin '%s' of package '%s' failed to load for some reason. Error:\n%s", base_class.c_str(), package.c_str(), e.what());
      return false;
    }

    return true;
  }
  /**
   * @brief Returns reference to a list of added ClassLoader
   * @return Const reference to ClassLoader
   */
  static const PluginLoaderVector& getPluginClassLoader();

  /**
   * @brief Instantiation of plugin using ClassLoader
   * @param type The name of the class to load
   * @return false, if instantiation has failed, otherwise true
   */
  static bool addPlugins(const std::vector<msgs::PluginDescription>& plugin_descriptions);
  static bool addPlugin(const msgs::PluginDescription& plugin_description);
  static bool addPluginByName(const std::string& name);

  template<typename PluginDerivedClass>
  static void addPlugin()
  {
    addPlugin(new PluginDerivedClass());
  }
  static void addPlugin(Plugin* plugin); // this function takes over pointer and will free memory automatically, when plugin is removed
  static void addPlugin(Plugin::Ptr plugin);

  /**
   * Returns first found plugin matching typename T. If specific element should be returned, do set name.
   */
  template<typename T>
  static bool getPlugin(boost::shared_ptr<T>& plugin, const std::string& name = std::string())
  {
    plugin.reset();

    // name specific search
    if (name.size())
    {
      Plugin::Ptr p;
      if (getPluginByName(name, p))
      {
        plugin = boost::dynamic_pointer_cast<T>(p);
        if (plugin)
          return true;
      }

      ROS_ERROR("[PluginManager] Couldn't find any matching plugin named '%s'!", name.c_str());
      return false;
    }
    // type specific search
    else
    {
      for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end(); itr++)
      {
        plugin = boost::dynamic_pointer_cast<T>(itr->second);
        if (plugin)
          return true;
      }

      ROS_ERROR("[PluginManager] Couldn't find any matching plugin!");
      return false;
    }
    return false;
  }

  static bool getPluginByName(const std::string& name, Plugin::Ptr& plugin);

  /// return all plugins derived by class T in alphabetical order (name)
  template<typename T>
  static bool getPluginsByType(std::vector<boost::shared_ptr<T> >& plugins)
  {
    plugins.clear();

    for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end(); itr++)
    {
      boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
      if (plugin)
        plugins.push_back(plugin);
    }

    return !plugins.empty();
  }
  static bool getPluginsByTypeClass(const std::string& type_class, std::vector<Plugin::Ptr>& plugins);

  /// returns a plugin marked as unique of specific type id
  static bool getUniquePluginByTypeClass(const std::string& type_class, Plugin::Ptr& plugin);

  static void getPluginDescriptions(std::vector<msgs::PluginDescription>& descriptions, msgs::PluginDescription filter = msgs::PluginDescription());
  static void getPluginStates(std::vector<msgs::PluginState>& plugin_states, msgs::PluginDescription filter = msgs::PluginDescription());

  static bool removePlugins(const std::vector<msgs::PluginDescription>& plugin_descriptions);
  static bool removePlugin(const msgs::PluginDescription& plugin_description);
  static bool removePluginByName(const std::string& name);

  static void removePlugin(Plugin::Ptr& plugin);

  template<typename T>
  static void removePluginsByType()
  {
    for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end();)
    {
      boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
      if (plugin)
        removePluginByName(itr++->first);
      else<commit_msg>added plugin getter for map container<commit_after>//=================================================================================================
// Copyright (c) 2015, <NAME>, TU Darmstadt
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Simulation, Systems Optimization and Robotics
//       group, TU Darmstadt nor the names of its contributors may be used to
//       endorse or promote products derived from this software without
//       specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//=================================================================================================

#ifndef VIGIR_PLUGINLIB_PLUGIN_MANAGER_H__
#define VIGIR_PLUGINLIB_PLUGIN_MANAGER_H__

#include <ros/ros.h>

#include <actionlib/server/simple_action_server.h>

#include <boost/noncopyable.hpp>

#include <vigir_generic_params/parameter_manager.h>

#include <vigir_pluginlib/plugin_loader.h>
#include <vigir_pluginlib/plugin.h>

#include <vigir_pluginlib_msgs/pluginlib_msgs.h>



namespace vigir_pluginlib
{
typedef actionlib::SimpleActionServer<msgs::GetPluginDescriptionsAction>  GetPluginDescriptionsActionServer;
typedef actionlib::SimpleActionServer<msgs::GetPluginStatesAction>        GetPluginStatesActionServer;
typedef actionlib::SimpleActionServer<msgs::PluginManagementAction>       PluginManagementActionServer;

class PluginManager
  : boost::noncopyable
{
protected:
  PluginManager();

public:
  typedef std::vector<PluginLoaderBase*> PluginLoaderVector;

  ~PluginManager();

  /**
   * @brief Initialize all rostopic/-services within the namespace of the given nodehandle
   * @param nh The nodehandle which is used to setup all topics/services
   */
  static void initialize(ros::NodeHandle& nh);

  /**
   * @brief Tries to extract plugin description from param server using the given name
   * @param name Name of the plugin
   * @param plugin_description Output of extracted plugin description
   * @return True if extraction was successful
   */
  static bool autocompletePluginDescriptionByName(const std::string& name, msgs::PluginDescription& plugin_description);

  /**
   * @brief Adds ClassLoader for a specific type of plugins
   * @param package The package containing the base class
   * @param base_class The type of the base class for classes to be loaded
   * @param attrib_name The attribute to search for in manifext.xml files, defaults to "plugin"
   * @param plugin_xml_paths The list of paths of plugin.xml files, defaults to be crawled via ros::package::getPlugins()
   * @exception pluginlib::LibraryLoadException Thrown if package manifest cannot be found
   */
  template<class PluginBaseClass>
  static bool addPluginClassLoader(const std::string& package, const std::string& base_class, const std::string& attrib_name = std::string("plugin"), const std::vector<std::string>& plugin_xml_paths = std::vector<std::string>())
  {
    // check for duplicate
    for (PluginLoaderBase* loader : Instance()->class_loader)
    {
      if (loader->getBaseClassType() == base_class)
      {
        ROS_DEBUG("[PluginManager] The ClassLoader for plugins of type '%s' has been already added!", base_class.c_str());
        return false;
      }
    }

    try
    {
      PluginLoader<PluginBaseClass>* loader = new PluginLoader<PluginBaseClass>(package, base_class, attrib_name, plugin_xml_paths);
      Instance()->class_loader.push_back(loader);
      ROS_INFO("[PluginManager] Added ClassLoader for plugins of type '%s'.", base_class.c_str());
      ROS_DEBUG("  Declared classes:");
      for (const std::string s : loader->getDeclaredClasses())
        ROS_DEBUG("    %s", s.c_str());
      ROS_DEBUG("  Registered libraries:");
      for (const std::string s : loader->getRegisteredLibraries())
        ROS_DEBUG("    %s", s.c_str());
    }
    catch (pluginlib::LibraryLoadException& e)
    {
      ROS_ERROR("[PluginManager] The ClassLoader for plugin '%s' of package '%s' failed to load for some reason. Error:\n%s", base_class.c_str(), package.c_str(), e.what());
      return false;
    }

    return true;
  }
  /**
   * @brief Returns reference to a list of added ClassLoader
   * @return Const reference to ClassLoader
   */
  static const PluginLoaderVector& getPluginClassLoader();

  /**
   * @brief Instantiation of plugin using ClassLoader
   * @param type The name of the class to load
   * @return false, if instantiation has failed, otherwise true
   */
  static bool addPlugins(const std::vector<msgs::PluginDescription>& plugin_descriptions);
  static bool addPlugin(const msgs::PluginDescription& plugin_description);
  static bool addPluginByName(const std::string& name);

  template<typename PluginDerivedClass>
  static void addPlugin()
  {
    addPlugin(new PluginDerivedClass());
  }
  static void addPlugin(Plugin* plugin); // this function takes over pointer and will free memory automatically, when plugin is removed
  static void addPlugin(Plugin::Ptr plugin);

  /**
   * Returns first found plugin matching typename T. If specific element should be returned, do set name.
   */
  template<typename T>
  static bool getPlugin(boost::shared_ptr<T>& plugin, const std::string& name = std::string())
  {
    plugin.reset();

    // name specific search
    if (name.size())
    {
      Plugin::Ptr p;
      if (getPluginByName(name, p))
      {
        plugin = boost::dynamic_pointer_cast<T>(p);
        if (plugin)
          return true;
      }

      ROS_ERROR("[PluginManager] Couldn't find any matching plugin named '%s'!", name.c_str());
      return false;
    }
    // type specific search
    else
    {
      for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end(); itr++)
      {
        plugin = boost::dynamic_pointer_cast<T>(itr->second);
        if (plugin)
          return true;
      }

      ROS_ERROR("[PluginManager] Couldn't find any matching plugin!");
      return false;
    }
    return false;
  }

  static bool getPluginByName(const std::string& name, Plugin::Ptr& plugin);

  /// returns all plugins derived by class T in alphabetical order (name)
  template<typename T>
  static bool getPluginsByType(std::vector<boost::shared_ptr<T> >& plugins)
  {
    plugins.clear();

    for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end(); itr++)
    {
      boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
      if (plugin)
        plugins.push_back(plugin);
    }

    return !plugins.empty();
  }
  /// returns all plugins derived by class T as map
  template<typename T>
  static bool getPluginsByType(std::map<std::string, boost::shared_ptr<T> >& plugins)
  {
    plugins.clear();

    for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end(); itr++)
    {
      boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
      if (plugin)
        plugins[itr->first] = plugin;
    }

    return !plugins.empty();
  }
  static bool getPluginsByTypeClass(const std::string& type_class, std::vector<Plugin::Ptr>& plugins);

  /// returns a plugin marked as unique of specific type id
  static bool getUniquePluginByTypeClass(const std::string& type_class, Plugin::Ptr& plugin);

  static void getPluginDescriptions(std::vector<msgs::PluginDescription>& descriptions, msgs::PluginDescription filter = msgs::PluginDescription());
  static void getPluginStates(std::vector<msgs::PluginState>& plugin_states, msgs::PluginDescription filter = msgs::PluginDescription());

  static bool removePlugins(const std::vector<msgs::PluginDescription>& plugin_descriptions);
  static bool removePlugin(const msgs::PluginDescription& plugin_description);
  static bool removePluginByName(const std::string& name);

  static void removePlugin(Plugin::Ptr& plugin);

  template<typename T>
  static void removePluginsByType()
  {
    for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name.begin(); itr != Instance()->plugins_by_name.end();)
    {
      boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
      if (plugin)
        removePluginByName(itr++->first);
      else
{'fraction_non_alphanumeric': 0.12422694272653939, 'fraction_numerical': 0.0004302231782737295, 'mean_word_length': 4.278455861481691, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6644132', 'n_tokens_mistral': 5210, 'n_tokens_neox': 4998, 'n_words': 1622}