Skip to content

Commit 5a2a410

Browse files
alxbilgerepernodhugtalbot
authored
[Core] Search parent in whole map, not only first element (#5753)
* [Core] Search parent in whole map, not only first element * fix for old compilers * [Core] Search parent in whole map, not only first element * fix for old compilers * Add small description of ClassEntryMap registry * Add comments for CreatorMap and ClassEntryMap * try to be more expressive * dllexport of BaseObjectCreator --------- Co-authored-by: erik pernod <erik.pernod@gmail.com> Co-authored-by: Hugo <hugo.talbot@sofa-framework.org>
1 parent f05c83a commit 5a2a410

File tree

7 files changed

+88
-62
lines changed

7 files changed

+88
-62
lines changed

Sofa/framework/Core/src/sofa/core/CategoryLibrary.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace sofa::core
2727
{
2828

2929

30-
typedef sofa::core::ObjectFactory::Creator Creator;
30+
using Creator = sofa::core::ObjectFactory::BaseObjectCreator;
3131

3232
/**
3333
* \brief An Generic Category of the Sofa Library

Sofa/framework/Core/src/sofa/core/ObjectFactory.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,18 @@ bool ObjectFactory::hasCreator(std::string classname)
5858

5959
std::string ObjectFactory::shortName(std::string classname)
6060
{
61-
std::string shortname;
62-
6361
const ClassEntryMap::iterator it = registry.find(classname);
6462
if (it != registry.end())
6563
{
6664
const ClassEntry::SPtr entry = it->second;
6765
if(!entry->creatorMap.empty())
6866
{
69-
const CreatorMap::iterator myit = entry->creatorMap.begin();
70-
const Creator::SPtr c = myit->second;
71-
shortname = c->getClass()->shortName;
67+
const auto firstElement = entry->creatorMap.begin();
68+
const BaseObjectCreator::SPtr c = firstElement->second;
69+
return c->getClass()->shortName;
7270
}
7371
}
74-
return shortname;
72+
return {};
7573
}
7674

7775
bool ObjectFactory::addAlias(std::string name, std::string target, bool force,
@@ -95,7 +93,8 @@ bool ObjectFactory::addAlias(std::string name, std::string target, bool force,
9593
return false;
9694
}
9795

98-
if (previous) {
96+
if (previous)
97+
{
9998
const ClassEntry::SPtr& entry = aliasEntry;
10099
*previous = entry;
101100
}
@@ -113,9 +112,9 @@ void ObjectFactory::resetAlias(std::string name, ClassEntry::SPtr previous)
113112

114113
void findTemplatedCreator(
115114
objectmodel::BaseContext* context,
116-
const ObjectFactory::Creator::SPtr& creator, const std::string& templateName,
115+
const ObjectFactory::BaseObjectCreator::SPtr& creator, const std::string& templateName,
117116
std::map<std::string, std::vector<std::string>>& creatorsErrors,
118-
std::vector< std::pair<std::string, ObjectFactory::Creator::SPtr> >& creators,
117+
std::vector< std::pair<std::string, ObjectFactory::BaseObjectCreator::SPtr> >& creators,
119118
objectmodel::BaseObjectDescription* arg)
120119
{
121120
if (helper::system::PluginManager::getInstance().isPluginUnloaded(creator->getTarget()))
@@ -142,7 +141,7 @@ void findTemplatedCreator(
142141
objectmodel::BaseObject::SPtr ObjectFactory::createObject(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg)
143142
{
144143
objectmodel::BaseObject::SPtr object = nullptr;
145-
std::vector< std::pair<std::string, Creator::SPtr> > creators;
144+
std::vector< std::pair<std::string, BaseObjectCreator::SPtr> > creators;
146145
std::string classname = arg->getAttribute( "type", "");
147146
std::string usertemplatename = arg->getAttribute( "template", "");
148147
ClassEntry::SPtr entry ;
@@ -487,9 +486,9 @@ void ObjectFactory::getEntriesFromTarget(std::vector<ClassEntry::SPtr>& result,
487486
{
488487

489488
bool inTarget = false;
490-
for (CreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
489+
for (ObjectTemplateCreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
491490
{
492-
const Creator::SPtr c = itc->second;
491+
const BaseObjectCreator::SPtr c = itc->second;
493492
if (target == c->getTarget())
494493
{
495494
inTarget = true;
@@ -538,7 +537,7 @@ void ObjectFactory::dump(std::ostream& out)
538537
out << " license : " << entry->license << "\n";
539538
if (!entry->documentationURL.empty())
540539
out << " documentation : " << entry->documentationURL << "\n";
541-
for (CreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
540+
for (ObjectTemplateCreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
542541
{
543542
out << " template instance : " << itc->first << "\n";
544543
}
@@ -580,7 +579,7 @@ void ObjectFactory::dumpXML(std::ostream& out)
580579
out << "<license>"<<entry->license<<"</license>\n";
581580
if (!entry->documentationURL.empty())
582581
out << "<documentation>"<<entry->documentationURL<<"</documentation>\n";
583-
for (CreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
582+
for (ObjectTemplateCreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
584583
{
585584
out << "<creator";
586585
if (!itc->first.empty()) out << " template=\"" << xmlencode(itc->first) << "\"";
@@ -617,7 +616,7 @@ void ObjectFactory::dumpHTML(std::ostream& out)
617616
if (entry->creatorMap.size()>2 || (entry->creatorMap.size()==1 && !entry->creatorMap.begin()->first.empty()))
618617
{
619618
out << "<li>Template instances:<i>";
620-
for (CreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
619+
for (ObjectTemplateCreatorMap::iterator itc = entry->creatorMap.begin(), itcend = entry->creatorMap.end(); itc != itcend; ++itc)
621620
{
622621
if (itc->first == entry->defaultTemplate)
623622
out << " <b>" << xmlencode(itc->first) << "</b>";
@@ -679,7 +678,7 @@ ObjectRegistrationData& ObjectRegistrationData::addDocumentationURL(std::string
679678

680679
ObjectRegistrationData& ObjectRegistrationData::addCreator(std::string classname,
681680
std::string templatename,
682-
ObjectFactory::Creator::SPtr creator)
681+
ObjectFactory::BaseObjectCreator::SPtr creator)
683682
{
684683

685684
if (!entry.className.empty() && entry.className != classname)
@@ -831,7 +830,7 @@ RegisterObject& RegisterObject::addDocumentationURL(std::string url)
831830
}
832831

833832
RegisterObject& RegisterObject::addCreator(std::string classname, std::string templatename,
834-
ObjectFactory::Creator::SPtr creator)
833+
ObjectFactory::BaseObjectCreator::SPtr creator)
835834
{
836835
m_objectRegistrationdata.addCreator(classname, templatename, creator);
837836
return *this;

Sofa/framework/Core/src/sofa/core/ObjectFactory.h

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,34 @@ namespace sofa::helper::system
3838
namespace sofa::core
3939
{
4040

41+
class ObjectRegistrationData;
42+
43+
typedef std::function<void(sofa::core::objectmodel::Base*, sofa::core::objectmodel::BaseObjectDescription*)> OnCreateCallback ;
44+
4145
/**
4246
* \brief Main class used to register and dynamically create objects
4347
*
44-
* It uses the Factory design pattern, where each class is registered in a map,
48+
* It uses the Factory design pattern, where each class is registered in a map
4549
* and dynamically retrieved given the type name.
4650
*
47-
* It also stores metainformation on each classes, such as description,
51+
* It also stores metainformation on each class, such as description,
4852
* authors, license, and available template types.
49-
*
50-
* \see RegisterObject for how new classes should be registered.
51-
*
5253
*/
53-
54-
class ObjectRegistrationData;
55-
56-
typedef std::function<void(sofa::core::objectmodel::Base*, sofa::core::objectmodel::BaseObjectDescription*)> OnCreateCallback ;
5754
class SOFA_CORE_API ObjectFactory
5855
{
5956
public:
6057

61-
/// Abstract interface of objects used to create instances of a given type
62-
class Creator
58+
/**
59+
* Abstract interface used to create instances (object) of a given type
60+
* See the derived class @ref ObjectCreator.
61+
*/
62+
class SOFA_CORE_API BaseObjectCreator
6363
{
6464
public:
65-
typedef std::shared_ptr<Creator> SPtr;
65+
using SPtr = std::shared_ptr<BaseObjectCreator>;
66+
67+
virtual ~BaseObjectCreator() = default;
6668

67-
virtual ~Creator() { }
6869
/// Pre-construction check.
6970
///
7071
/// \return true if the object can be created successfully.
@@ -75,24 +76,31 @@ class SOFA_CORE_API ObjectFactory
7576
/// \pre canCreate(context, arg) == true.
7677
virtual objectmodel::BaseObject::SPtr createInstance(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg) = 0;
7778

78-
/// type_info structure associated with the type of intanciated objects.
79+
/// type_info structure associated with the type of instantiated objects.
7980
virtual const std::type_info& type() = 0;
8081

81-
/// BaseClass structure associated with the type of intanciated objects.
82+
/// BaseClass structure associated with the type of instantiated objects.
8283
virtual const objectmodel::BaseClass* getClass() = 0;
8384

8485
/// The name of the library or executable containing the binary code for this component
8586
virtual const char* getTarget() = 0;
8687

8788
virtual const char* getHeaderFileLocation() = 0;
8889
};
89-
typedef std::map<std::string, Creator::SPtr> CreatorMap;
90+
using Creator SOFA_CORE_DEPRECATED_RENAME_CREATOR_BASEOBJECTCREATOR() = BaseObjectCreator;
91+
92+
using TemplateName = std::string;
93+
94+
/// For a given templated class, the map stores all creators and the key is the template name.
95+
using ObjectTemplateCreatorMap = std::map<TemplateName, BaseObjectCreator::SPtr>;
96+
97+
using CreatorMap SOFA_CORE_DEPRECATED_RENAME_CREATORMAP_OBJECTTEMPLATECREATORMAP() = ObjectTemplateCreatorMap;
9098

9199
/// Record storing information about a class
92100
class ClassEntry
93101
{
94102
public:
95-
typedef std::shared_ptr<ClassEntry> SPtr;
103+
using SPtr = std::shared_ptr<ClassEntry>;
96104

97105
std::string className;
98106
std::set<std::string> aliases;
@@ -101,14 +109,20 @@ class SOFA_CORE_API ObjectFactory
101109
std::string license;
102110
std::string documentationURL;
103111
std::string defaultTemplate;
104-
CreatorMap creatorMap;
112+
ObjectTemplateCreatorMap creatorMap; // to create instances of the class for different templates
105113
std::map<std::string, std::vector<std::string>> m_dataAlias ;
106114
};
107-
typedef std::map<std::string, ClassEntry::SPtr> ClassEntryMap;
115+
116+
using ClassName = std::string;
117+
118+
/// Map to store all class entries, key is the class name.
119+
using ClassEntryMap = std::map<ClassName, ClassEntry::SPtr>;
108120

109121
protected:
110-
/// Main class registry
122+
123+
/// Main registry of all classes
111124
ClassEntryMap registry;
125+
112126
OnCreateCallback m_callbackOnCreate ;
113127

114128
/// Keep track of plugins who already registered
@@ -217,20 +231,24 @@ template<class BaseClass>
217231
void ObjectFactory::getEntriesDerivedFrom(std::vector<ClassEntry::SPtr>& result) const
218232
{
219233
result.clear();
220-
for (const auto& r : registry)
234+
for (const auto& [mapKeyClassName, entryInRegistry] : registry)
221235
{
222-
ClassEntry::SPtr entry = r.second;
223-
// Push the entry only if it is not an alias
224-
if (entry->className == r.first)
236+
// Discard the entry if its class name is not consistent with its key in the map.
237+
// Differences happen for class aliases.
238+
if (entryInRegistry->className == mapKeyClassName)
225239
{
226-
const auto creatorEntry = entry->creatorMap.begin();
227-
if (creatorEntry != entry->creatorMap.end())
228-
{
229-
const auto* baseClass = creatorEntry->second->getClass();
230-
if (baseClass && baseClass->hasParent(BaseClass::GetClass()))
240+
const auto& templateCreators = entryInRegistry->creatorMap;
241+
const auto isAnyInstantiationDerived = std::any_of(templateCreators.begin(), templateCreators.end(),
242+
[](const auto& it)
231243
{
232-
result.push_back(entry);
233-
}
244+
const auto& templateInstantiation = it.second;
245+
const auto* instantiationClass = templateInstantiation->getClass();
246+
return instantiationClass
247+
&& instantiationClass->hasParent(BaseClass::GetClass());
248+
});
249+
if (isAnyInstantiationDerived) //at least one template instantiation of the class is derived from BaseClass
250+
{
251+
result.push_back(entryInRegistry);
234252
}
235253
}
236254
}
@@ -241,21 +259,16 @@ std::string ObjectFactory::listClassesDerivedFrom(const std::string& separator)
241259
{
242260
std::vector<ClassEntry::SPtr> entries;
243261
getEntriesDerivedFrom<BaseClass>(entries);
244-
if (entries.empty()) return std::string();
245262

246-
const auto join = [&separator](std::string a, ClassEntry::SPtr b)
247-
{
248-
return std::move(a) + separator + b->className;
249-
};
250-
return std::accumulate(std::next(entries.begin()), entries.end(),
251-
entries.front()->className, join);
263+
return sofa::helper::join(entries.begin(), entries.end(),
264+
[](const ClassEntry::SPtr& entry){ return entry->className;}, separator);
252265
}
253266

254267
/**
255268
* \brief Typed Creator class used to create instances of object type RealObject
256269
*/
257270
template<class RealObject>
258-
class ObjectCreator : public ObjectFactory::Creator
271+
class ObjectCreator : public ObjectFactory::BaseObjectCreator
259272
{
260273
public:
261274
bool canCreate(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg) override
@@ -339,7 +352,7 @@ class SOFA_CORE_API ObjectRegistrationData
339352
///
340353
/// See the add<RealObject>() method for an easy way to add a Creator.
341354
ObjectRegistrationData& addCreator(std::string classname, std::string templatename,
342-
ObjectFactory::Creator::SPtr creator);
355+
ObjectFactory::BaseObjectCreator::SPtr creator);
343356

344357
/// Add a template instantiation of this class.
345358
///
@@ -398,7 +411,7 @@ class SOFA_ATTRIBUTE_DEPRECATED__REGISTEROBJECT() SOFA_CORE_API RegisterObject
398411
RegisterObject& addLicense(std::string val);
399412
RegisterObject& addDocumentationURL(std::string url);
400413
RegisterObject& addCreator(std::string classname, std::string templatename,
401-
ObjectFactory::Creator::SPtr creator);
414+
ObjectFactory::BaseObjectCreator::SPtr creator);
402415

403416
template<class RealObject>
404417
RegisterObject& add(bool defaultTemplate = false)

Sofa/framework/Core/src/sofa/core/ObjectFactoryJson.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ inline void to_json(nlohmann::json& json,
9393
}
9494

9595
inline void to_json(nlohmann::json& json,
96-
const sofa::core::ObjectFactory::Creator::SPtr& creator)
96+
const sofa::core::ObjectFactory::BaseObjectCreator::SPtr& creator)
9797
{
9898
if (creator)
9999
{

Sofa/framework/Core/src/sofa/core/SofaLibrary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void SofaLibrary::build( const std::vector< std::string >& examples)
4444
for (std::size_t i=0; i<entries.size(); ++i)
4545
{
4646
//Insert Template specification
47-
ObjectFactory::CreatorMap::iterator creatorEntry = entries[i]->creatorMap.begin();
47+
ObjectFactory::ObjectTemplateCreatorMap::iterator creatorEntry = entries[i]->creatorMap.begin();
4848
if (creatorEntry != entries[i]->creatorMap.end())
4949
{
5050
const objectmodel::BaseClass* baseClass = creatorEntry->second->getClass();

Sofa/framework/Core/src/sofa/core/config.h.in

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,17 @@ SOFA_ATTRIBUTE_DEPRECATED("v25.12", "v26.06", "Use getContactDistance or setCont
169169
#define SOFA_CORE_ATTRIBUTE_REMOVE_ASSEMBLY_API() \
170170
SOFA_ATTRIBUTE_DISABLED("v25.12", "v25.12", "The assembly of the linear system is no longer the responsibility of the solver. Instead, a linear system component lives along with the linear solver. This component is in charge of the assembly.")
171171
#endif
172+
173+
#ifdef SOFA_BUILD_SOFA_CORE
174+
#define SOFA_CORE_DEPRECATED_RENAME_CREATOR_BASEOBJECTCREATOR()
175+
#else
176+
#define SOFA_CORE_DEPRECATED_RENAME_CREATOR_BASEOBJECTCREATOR() \
177+
SOFA_ATTRIBUTE_DISABLED("v25.12", "v26.06", "Type Creator has been renamed to BaseObjectCreator.")
178+
#endif
179+
180+
#ifdef SOFA_BUILD_SOFA_CORE
181+
#define SOFA_CORE_DEPRECATED_RENAME_CREATORMAP_OBJECTTEMPLATECREATORMAP()
182+
#else
183+
#define SOFA_CORE_DEPRECATED_RENAME_CREATORMAP_OBJECTTEMPLATECREATORMAP() \
184+
SOFA_ATTRIBUTE_DISABLED("v25.12", "v26.06", "Type CreatorMap has been renamed to ObjectTemplateCreatorMap.")
185+
#endif

applications/projects/SceneChecking/src/SceneChecking/SceneCheckMissingRequiredPlugin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void SceneCheckMissingRequiredPlugin::doCheckOn(sofa::simulation::Node* node)
5656
const ObjectFactory::ClassEntry entry = ObjectFactory::getInstance()->getEntry(object->getClassName());
5757
if(!entry.creatorMap.empty())
5858
{
59-
ObjectFactory::CreatorMap::const_iterator it = entry.creatorMap.find(object->getTemplateName());
59+
ObjectFactory::ObjectTemplateCreatorMap::const_iterator it = entry.creatorMap.find(object->getTemplateName());
6060
if(entry.creatorMap.end() != it && *it->second->getTarget())
6161
{
6262
const std::string pluginName = it->second->getTarget();

0 commit comments

Comments
 (0)