AutoAPMS
Resilient Robot Mission Management
Loading...
Searching...
No Matches
resource.hpp
1// Copyright 2024 Robin Müller
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <map>
18#include <set>
19#include <string>
20#include <type_traits>
21#include <vector>
22
23#include "auto_apms_util/container.hpp"
24#include "auto_apms_util/exceptions.hpp"
25#include "auto_apms_util/string.hpp"
26#include "pluginlib/class_loader.hpp"
27
28namespace auto_apms_util
29{
30
33
46std::set<std::string> getPackagesWithResourceType(
47 const std::string & resource_type, const std::set<std::string> & exclude_packages = {});
48
60std::set<std::string> getPackagesWithPluginResources(const std::set<std::string> & exclude_packages = {});
61
73std::string getPluginXMLPath(const std::string & package);
74
86std::vector<std::string> collectPluginXMLPaths(const std::set<std::string> & exclude_packages = {});
87
89
90// clang-format off
113// clang-format on
114template <typename BaseT>
115class PluginClassLoader : public pluginlib::ClassLoader<BaseT>
116{
117public:
133 const std::string & base_package, const std::string & base_class,
134 const std::set<std::string> & exclude_packages = {});
135
160 const std::string & base_package, const std::string & base_class,
161 const std::set<std::string> & exclude_packages = {},
162 const std::map<std::string, std::string> & reserved_names = {});
163
168 std::map<std::string, std::string> getClassPackageMap();
169};
170
171// #####################################################################################################################
172// ################################ DEFINITIONS ##############################################
173// #####################################################################################################################
174
175template <typename BaseT>
177 const std::string & base_package, const std::string & base_class, const std::set<std::string> & exclude_packages)
178: pluginlib::ClassLoader<BaseT>(base_package, base_class, "", collectPluginXMLPaths(exclude_packages))
179{
180}
181
182template <typename BaseT>
184 const std::string & base_package, const std::string & base_class, const std::set<std::string> & exclude_packages,
185 const std::map<std::string, std::string> & reserved_names)
186{
187 std::map<std::string, std::vector<std::string>> packages_for_class_name;
188 const std::set<std::string> packages =
189 getPackagesWithResourceType(_AUTO_APMS_UTIL__RESOURCE_TYPE_NAME__PLUGINLIB, exclude_packages);
190 for (const auto & package : packages) {
191 auto single_package_loader =
192 pluginlib::ClassLoader<BaseT>(base_package, base_class, "", {getPluginXMLPath(package)});
193 for (const auto & class_name : single_package_loader.getDeclaredClasses()) {
194 packages_for_class_name[class_name].push_back(package);
195 }
196 }
197
198 // Reserved class names are considered as declared
199 for (const auto & [class_name, package] : reserved_names) {
200 packages_for_class_name[class_name].push_back(package + "(Build package)");
201 }
202
203 // Determine if there are duplicate class names
204 std::vector<std::string> error_details;
205 for (const auto & [class_name, packages] : packages_for_class_name) {
206 if (packages.size() > 1) {
207 error_details.push_back(
208 "- Class '" + class_name + "' found in packages ['" + auto_apms_util::join(packages, "', '") + "'].");
209 }
210 }
211 if (!error_details.empty()) {
212 throw exceptions::ResourceError(
213 "Ambiguous class names found! PluginClassLoader (Base: '" + base_class +
214 "') created with makeUnambiguousPluginClassLoader() won't register resources from packages "
215 "that use already existing lookup names. Found the following duplicates:\n" +
216 auto_apms_util::join(error_details, "\n"));
217 }
218 return {base_package, base_class, exclude_packages};
219}
220
221template <typename BaseT>
222inline std::map<std::string, std::string> PluginClassLoader<BaseT>::getClassPackageMap()
223{
224 std::map<std::string, std::string> map;
225 for (const std::string & class_name : this->getDeclaredClasses()) {
226 map[class_name] = this->getClassPackage(class_name);
227 }
228 return map;
229}
230
231} // namespace auto_apms_util
static PluginClassLoader makeUnambiguousPluginClassLoader(const std::string &base_package, const std::string &base_class, const std::set< std::string > &exclude_packages={}, const std::map< std::string, std::string > &reserved_names={})
Parse all associated plugin manifest files registered with the ament resource index and instantiate a...
Definition resource.hpp:183
std::map< std::string, std::string > getClassPackageMap()
Retrieve a map that contains information about which package a plugin class belongs to.
Definition resource.hpp:222
PluginClassLoader(const std::string &base_package, const std::string &base_class, const std::set< std::string > &exclude_packages={})
Standard PluginClassLoader constructor.
Definition resource.hpp:176
std::vector< std::string > collectPluginXMLPaths(const std::set< std::string > &exclude_packages={})
Collect the paths of plugin.xml manifest files used for initializing pluginlib::ClassLoader objects.
Definition resource.cpp:76
std::string getPluginXMLPath(const std::string &package)
Get the path of a plugin.xml manifest file used for initializing pluginlib::ClassLoader objects.
Definition resource.cpp:57
std::set< std::string > getPackagesWithResourceType(const std::string &resource_type, const std::set< std::string > &exclude_packages={})
Get a list of all package names that register a certain type of ament_index resources.
Definition resource.cpp:28
std::set< std::string > getPackagesWithPluginResources(const std::set< std::string > &exclude_packages={})
Get a list of all package names that register AutoAPMS plugin resources.
Definition resource.cpp:52
Fundamental helper classes and utility functions.