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
95template <typename BaseT>
96class PluginClassLoader : public pluginlib::ClassLoader<BaseT>
97{
98public:
114 const std::string & base_package, const std::string & base_class,
115 const std::set<std::string> & exclude_packages = {});
116
141 const std::string & base_package, const std::string & base_class,
142 const std::set<std::string> & exclude_packages = {},
143 const std::map<std::string, std::string> & reserved_names = {});
144
145 std::map<std::string, std::string> getClassPackageMap();
146};
147
148// #####################################################################################################################
149// ################################ DEFINITIONS ##############################################
150// #####################################################################################################################
151
152template <typename BaseT>
154 const std::string & base_package, const std::string & base_class, const std::set<std::string> & exclude_packages)
155: pluginlib::ClassLoader<BaseT>(base_package, base_class, "", collectPluginXMLPaths(exclude_packages))
156{
157}
158
159template <typename BaseT>
161 const std::string & base_package, const std::string & base_class, const std::set<std::string> & exclude_packages,
162 const std::map<std::string, std::string> & reserved_names)
163{
164 std::map<std::string, std::vector<std::string>> packages_for_class_name;
165 const std::set<std::string> packages =
166 getPackagesWithResourceType(_AUTO_APMS_UTIL__RESOURCE_TYPE_NAME__PLUGINLIB, exclude_packages);
167 for (const auto & package : packages) {
168 auto single_package_loader =
169 pluginlib::ClassLoader<BaseT>(base_package, base_class, "", {getPluginXMLPath(package)});
170 for (const auto & class_name : single_package_loader.getDeclaredClasses()) {
171 packages_for_class_name[class_name].push_back(package);
172 }
173 }
174
175 // Reserved class names are considered as declared
176 for (const auto & [class_name, package] : reserved_names) {
177 packages_for_class_name[class_name].push_back(package + "(Build package)");
178 }
179
180 // Determine if there are duplicate class names
181 std::vector<std::string> error_details;
182 for (const auto & [class_name, packages] : packages_for_class_name) {
183 if (packages.size() > 1) {
184 error_details.push_back(
185 "- Class '" + class_name + "' found in packages ['" + auto_apms_util::join(packages, "', '") + "'].");
186 }
187 }
188 if (!error_details.empty()) {
189 throw exceptions::ResourceError(
190 "Ambiguous class names found! PluginClassLoader (Base: '" + base_class +
191 "') created with makeUnambiguousPluginClassLoader() won't register resources from packages "
192 "that use already existing lookup names. Found the following duplicates:\n" +
193 auto_apms_util::join(error_details, "\n"));
194 }
195 return {base_package, base_class, exclude_packages};
196}
197
198template <typename BaseT>
199inline std::map<std::string, std::string> PluginClassLoader<BaseT>::getClassPackageMap()
200{
201 std::map<std::string, std::string> map;
202 for (const std::string & class_name : this->getDeclaredClasses()) {
203 map[class_name] = this->getClassPackage(class_name);
204 }
205 return map;
206}
207
208} // 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:160
PluginClassLoader(const std::string &base_package, const std::string &base_class, const std::set< std::string > &exclude_packages={})
Standard PluginClassLoader constructor.
Definition resource.hpp:153
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.