Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ class MatrixLinearSolver<Matrix,Vector,NoThreadManager> : public BaseMatrixLinea
return ThreadManager::Name()+Matrix::Name();
}

static std::vector<std::string> GetTemplateNameAttributeList()
{
return {"matrixType"};
}

bool isAsyncSolver() override
{
return ThreadManager::isAsyncSolver();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ class MechanicalObject : public sofa::core::behavior::MechanicalState<DataTypes>
typedef typename DataTypes::MatrixDeriv::RowIterator MatrixDerivRowIterator;
typedef typename core::behavior::BaseMechanicalState::ConstraintBlock ConstraintBlock;

static std::vector<std::string> GetTemplateNameAttributeList()
{
return {"dofType"};
}

protected:
MechanicalObject();
public:
Expand Down
95 changes: 79 additions & 16 deletions Sofa/framework/Core/src/sofa/core/ObjectFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,69 @@ void findTemplatedCreator(
}
}

std::vector<std::string> replaceDeprecatedTemplates(std::vector<std::string>& templateNames)
{
std::vector<std::string> deprecatedTemplates;
for(auto& name : templateNames)
{
const sofa::defaulttype::TemplateAlias* alias = sofa::defaulttype::TemplateAliases::getTemplateAlias(name);
if( alias != nullptr )
{
assert(alias != nullptr);
/// This alias results in "undefined" behavior.
if( alias->second )
{
deprecatedTemplates.push_back("The deprecated template '"+name+"' has been replaced by "+alias->first+".");
}

name = alias->first;
}
}
return deprecatedTemplates;
}


std::optional<std::string> buildTemplateNamesFromAttributes(const ObjectFactory::ClassEntry& entry, objectmodel::BaseObjectDescription* arg)
{
assert(arg);
if (entry.templateNameAttributes.has_value())
{
const auto& attributeList = entry.templateNameAttributes.value();
if (attributeList.empty())
return {};

std::vector<std::string> attributeValues;

std::vector<std::string> foundAttributes;
std::vector<std::string> missingAttributes;

for (const auto& attributeName : attributeList)
{
if (auto* attr = arg->getAttribute(attributeName, nullptr))
{
foundAttributes.push_back(attributeName);
attributeValues.emplace_back(attr);
}
else
{
missingAttributes.push_back(attributeName);
}
}

if (!attributeValues.empty() && !missingAttributes.empty())
{
arg->logError("Found attributes '" + sofa::helper::join(missingAttributes, ", ") +
"', but not '" + sofa::helper::join(foundAttributes, ", ") +
"', preventing to deduce a template list");
}

replaceDeprecatedTemplates(attributeValues);
return sofa::helper::join(attributeValues, ",");
}

return {};
}

objectmodel::BaseComponent::SPtr ObjectFactory::createObject(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg)
{
objectmodel::BaseComponent::SPtr object = nullptr;
Expand All @@ -157,22 +220,8 @@ objectmodel::BaseComponent::SPtr ObjectFactory::createObject(objectmodel::BaseCo
/// type precision into a different one.
/// (4) rebuild the template string by joining them all with ','.
std::vector<std::string> usertemplatenames = sofa::helper::split(usertemplatename, ',');
std::vector<std::string> deprecatedTemplates;
for(auto& name : usertemplatenames)
{
const sofa::defaulttype::TemplateAlias* alias;
if( (alias=sofa::defaulttype::TemplateAliases::getTemplateAlias(name)) != nullptr )
{
assert(alias != nullptr);
/// This alias results in "undefined" behavior.
if( alias->second )
{
deprecatedTemplates.push_back("The deprecated template '"+name+"' has been replaced by "+alias->first+".");
}
std::vector<std::string> deprecatedTemplates = replaceDeprecatedTemplates(usertemplatenames);

name = alias->first;
}
}
std::string templatename = sofa::helper::join(usertemplatenames, ",");
std::string userresolved = templatename; // Copy in case we change for the default one
////////////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -194,11 +243,24 @@ objectmodel::BaseComponent::SPtr ObjectFactory::createObject(objectmodel::BaseCo
const auto previous_errors = arg->getErrors();
arg->clearErrors();

// For every classes in the registry
ClassEntryMap::iterator it = registry.find(classname);
if (it != registry.end()) // Found the classname
{
entry = it->second;

if (templatename.empty())
{
const auto templateNameFromAttributes = buildTemplateNamesFromAttributes(*entry, arg);
if (templateNameFromAttributes.has_value())
{
const auto& templateNameFromAttributesValue = templateNameFromAttributes.value();
if (entry->creatorMap.contains(templateNameFromAttributesValue))
{
templatename = templateNameFromAttributesValue;
}
}
}

// If no template has been given or if the template does not exist, first try with the default one
if(templatename.empty() || !entry->creatorMap.contains(templatename))
templatename = entry->defaultTemplate;
Expand Down Expand Up @@ -714,6 +776,7 @@ bool ObjectRegistrationData::commitTo(sofa::core::ObjectFactory* objectFactory)
reg.authors += entry.authors;
reg.license += entry.license;
reg.documentationURL += entry.documentationURL;
reg.templateNameAttributes = entry.templateNameAttributes;
if (!entry.defaultTemplate.empty())
{
if (!reg.defaultTemplate.empty())
Expand Down
16 changes: 15 additions & 1 deletion Sofa/framework/Core/src/sofa/core/ObjectFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <numeric>
#include <sofa/helper/Utils.h>
#include <sofa/url.h>
#include <optional>


namespace sofa::helper::system
Expand Down Expand Up @@ -110,7 +111,10 @@ class SOFA_CORE_API ObjectFactory
std::string documentationURL;
std::string defaultTemplate;
ObjectTemplateCreatorMap creatorMap; // to create instances of the class for different templates
std::map<std::string, std::vector<std::string>> m_dataAlias ;
std::map<std::string, std::vector<std::string>> m_dataAlias;

// list of keys.
std::optional<std::vector<std::string>> templateNameAttributes;
};

using ClassName = std::string;
Expand Down Expand Up @@ -363,6 +367,11 @@ class SOFA_CORE_API ObjectRegistrationData
const std::string classname = sofa::core::objectmodel::BaseClassNameHelper::getClassName<RealObject>();
const std::string templatename = sofa::core::objectmodel::BaseClassNameHelper::getTemplateName<RealObject>();

if constexpr (requires {RealObject::GetTemplateNameAttributeList(); })
{
entry.templateNameAttributes = RealObject::GetTemplateNameAttributeList();
}

if (defaultTemplate)
entry.defaultTemplate = templatename;

Expand All @@ -388,6 +397,11 @@ class SOFA_CORE_API ObjectRegistrationData
return addCreator(classname, templatename, objectCreator);
}

void addTemplateNameAttributeList(const std::initializer_list<std::string>& list)
{
entry.templateNameAttributes = list;
}

/// This is the final operation that will actually commit the additions to the ObjectFactory.
bool commitTo(sofa::core::ObjectFactory* objectFactory) const;

Expand Down
Loading