Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SofaGraphComponent] Refactor the SceneChecker and add a new SceneChecker to test dumplicated names. #392

Merged
1 change: 0 additions & 1 deletion SofaKernel/modules/SofaSimulationGraph/DAGNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ Node::SPtr DAGNode::createChild(const std::string& nodeName)
/// Add a child node
void DAGNode::doAddChild(DAGNode::SPtr node)
{
// printf("DAGNode::doAddChild this=%X(%s) child=%X(%s)\n",this,getName().c_str(),node.get(),node->getName().c_str());
child.add(node);
node->l_parents.add(this);
node->l_parents.updateLinks(); // to fix load-time unresolved links
Expand Down
6 changes: 6 additions & 0 deletions applications/sofa/gui/qt/RealGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,9 @@ void RealGUI::fileOpen ( std::string filename, bool temporaryFile, bool reload )
/// We want to warn user that there is component that are implemented in specific plugin
/// and that there is no RequiredPlugin in their scene.
SceneCheckerVisitor checker(ExecParams::defaultInstance()) ;
checker.addCheck(simulation::SceneCheckAPIChange::newSPtr());
checker.addCheck(simulation::SceneCheckDuplicatedName::newSPtr());
checker.addCheck(simulation::SceneCheckMissingRequiredPlugin::newSPtr());
checker.validate(mSimulation.get()) ;
}

Expand Down Expand Up @@ -901,6 +904,9 @@ void RealGUI::setSceneWithoutMonitor (Node::SPtr root, const char* filename, boo
/// We want to warn user that there is component that are implemented in specific plugin
/// and that there is no RequiredPlugin in their scene.
SceneCheckerVisitor checker(ExecParams::defaultInstance()) ;
checker.addCheck(simulation::SceneCheckAPIChange::newSPtr());
checker.addCheck(simulation::SceneCheckDuplicatedName::newSPtr());
checker.addCheck(simulation::SceneCheckMissingRequiredPlugin::newSPtr());
checker.validate(root.get()) ;

mSimulation = root;
Expand Down
2 changes: 2 additions & 0 deletions modules/SofaGraphComponent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(HEADER_FILES
SofaDefaultPathSetting.h
StatsSetting.h
ViewerSetting.h
SceneChecks.h
SceneCheckerVisitor.h
APIVersion.h
config.h
Expand All @@ -36,6 +37,7 @@ set(SOURCE_FILES
SofaDefaultPathSetting.cpp
StatsSetting.cpp
ViewerSetting.cpp
SceneChecks.cpp
SceneCheckerVisitor.cpp
APIVersion.cpp
initGraphComponent.cpp
Expand Down
116 changes: 26 additions & 90 deletions modules/SofaGraphComponent/SceneCheckerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@
* *
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#include <algorithm>
#include <sofa/version.h>

#include <sofa/core/ObjectFactory.h>
#include <sofa/helper/system/PluginManager.h>
#include <sofa/version.h>
#include <sofa/helper/system/FileRepository.h>

#include "SceneChecks.h"
#include "SceneCheckerVisitor.h"
#include "RequiredPlugin.h"

Expand All @@ -41,122 +45,54 @@ using sofa::core::ExecParams ;
using sofa::helper::system::PluginRepository ;
using sofa::helper::system::PluginManager ;


SceneCheckerVisitor::SceneCheckerVisitor(const ExecParams* params) : Visitor(params)
{
std::stringstream version;
version << SOFA_VERSION / 10000 << "." << SOFA_VERSION / 100 % 100;
m_currentApiLevel = version.str();

installChangeSets() ;
}


SceneCheckerVisitor::~SceneCheckerVisitor()
{
}

void SceneCheckerVisitor::addHookInChangeSet(const std::string& version, ChangeSetHookFunction fct)
{
m_changesets[version].push_back(fct) ;
}

void SceneCheckerVisitor::installChangeSets()
void SceneCheckerVisitor::addCheck(SceneCheck::SPtr check)
{
addHookInChangeSet("17.06", [](Base* o){
if(o->getClassName() == "RestShapeSpringsForceField" && o->findLink("external_rest_shape")->getSize() != 0)
msg_warning(o) << "RestShapeSpringsForceField have changed since 17.06. The parameter 'external_rest_shape' is now a Link. To fix your scene you need to add and '@' in front of the provided path. See PR#315" ;
}) ;

addHookInChangeSet("17.06", [](Base* o){
if(o->getClassName() == "BoxStiffSpringForceField" )
msg_warning(o) << "BoxStiffSpringForceField have changed since 17.06. To use the old behavior you need to set parameter 'forceOldBehavior=true'" ;
}) ;

addHookInChangeSet("17.06", [](Base* o){
if(o->getClassName() == "TheComponentWeWantToRemove" )
msg_warning(o) << "TheComponentWewantToRemove is deprecated since sofa 17.06. It have been replaced by TheSuperComponent. #See PR318" ;
}) ;
if( std::find(m_checkset.begin(), m_checkset.end(), check) == m_checkset.end() )
m_checkset.push_back(check) ;
}

void SceneCheckerVisitor::validate(Node* node)
{
enableValidationAPIVersion(node) ;
enableValidationRequiredPlugins(node) ;

msg_info("SceneChecker") << "Validating a scene: " << msgendl
<< "- APIVersion checking: " << m_isAPIVersionValidationEnabled << msgendl
<< "- RequiredPlugin checking: " << m_isRequiredPluginValidationEnabled ;

execute(node) ;
void SceneCheckerVisitor::removeCheck(SceneCheck::SPtr check)
{
m_checkset.erase( std::remove( m_checkset.begin(), m_checkset.end(), check ), m_checkset.end() );
}

void SceneCheckerVisitor::enableValidationAPIVersion(Node* node)
void SceneCheckerVisitor::validate(Node* node)
{
APIVersion* apiversion {nullptr} ;

/// 1. Find if there is an APIVersion component in the scene. If there is none, warn the user and set
/// the version to 17.06 (the last version before it was introduced). If there is one...use
/// this component to request the API version requested by the scene.
node->getTreeObject(apiversion) ;
if(!apiversion)
std::stringstream tmp;
for(SceneCheck::SPtr& check : m_checkset)
{
msg_info("SceneChecker") << "The 'APIVersion' directive is missing in the current scene. Switching to the default APIVersion level '"<< m_selectedApiLevel <<"' " ;
}
else
{
m_selectedApiLevel = apiversion->getApiLevel() ;
tmp << "- " << check->getName() << msgendl ;
check->doInit(node) ;
}

/// 2. We activate if the API level mis-match. In the future we may want to be able to handle
/// more precise way to track difference between version but for the moment let's take the
/// easy path for the developpers.
m_isAPIVersionValidationEnabled = m_selectedApiLevel != m_currentApiLevel ;
}
msg_info("SceneChecker") << "Validating node '"<< node->getPathName() << "'. " << msgendl
<< "Activate checkers: " << msgendl
<< tmp.str() ;

void SceneCheckerVisitor::enableValidationRequiredPlugins(Node* node)
{
helper::vector< RequiredPlugin* > plugins ;
node->getTreeObjects< RequiredPlugin >(&plugins) ;

for(auto& plugin : plugins)
m_requiredPlugins[plugin->getName()] = true ;
execute(node) ;
}


Visitor::Result SceneCheckerVisitor::processNodeTopDown(Node* node)
{
for (auto& object : node->object )
for(SceneCheck::SPtr& check : m_checkset)
{
if(m_isRequiredPluginValidationEnabled)
{
ObjectFactory::ClassEntry entry = ObjectFactory::getInstance()->getEntry(object->getClassName());
if(!entry.creatorMap.empty())
{
ObjectFactory::CreatorMap::iterator it = entry.creatorMap.find(object->getTemplateName());
if(entry.creatorMap.end() != it && *it->second->getTarget()){
std::string pluginName = it->second->getTarget() ;
std::string path = PluginManager::getInstance().findPlugin(pluginName) ;
if( PluginManager::getInstance().pluginIsLoaded(path)
&& m_requiredPlugins.find(pluginName) == m_requiredPlugins.end() )
{
msg_warning("SceneChecker")
<< "This scene is using component '" << object->getClassName() << "'. " << msgendl
<< "This component is part of the '" << pluginName << "' plugin but there is no <RequiredPlugin name='" << pluginName << "'> directive in your scene." << msgendl
<< "Your scene may not work on a sofa environment that does not have pre-loaded the plugin." << msgendl
<< "To fix your scene and remove this warning you need to add the RequiredPlugin directive at the beginning of your scene. ";
}
}
}
}
if(m_isAPIVersionValidationEnabled)
{
if(m_selectedApiLevel != m_currentApiLevel && m_changesets.find(m_selectedApiLevel) != m_changesets.end())
{
for(auto& hook : m_changesets[m_selectedApiLevel])
{
hook(object.get());
}
}
}
check->doCheckOn(node) ;
}

return RESULT_CONTINUE;
}

Expand Down
20 changes: 6 additions & 14 deletions modules/SofaGraphComponent/SceneCheckerVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@
#include <map>

#include <sofa/simulation/Visitor.h>
#include "SceneChecks.h"

/////////////////////////////////////// DECLARATION ////////////////////////////////////////////////
namespace sofa
{
namespace simulation
{
typedef std::function<void(sofa::core::objectmodel::Base*)> ChangeSetHookFunction ;

class SOFA_GRAPH_COMPONENT_API SceneCheckerVisitor : public Visitor
{
Expand All @@ -42,22 +43,13 @@ class SOFA_GRAPH_COMPONENT_API SceneCheckerVisitor : public Visitor
virtual ~SceneCheckerVisitor() ;

void validate(Node* node) ;

void enableValidationAPIVersion(Node *node) ;
void enableValidationRequiredPlugins(Node* node) ;

virtual Result processNodeTopDown(Node* node) override ;

void installChangeSets() ;
void addHookInChangeSet(const std::string& version, ChangeSetHookFunction fct) ;
private:
std::map<std::string,bool> m_requiredPlugins ;
bool m_isRequiredPluginValidationEnabled {true} ;
bool m_isAPIVersionValidationEnabled {true} ;
std::string m_currentApiLevel;
std::string m_selectedApiLevel {"17.06"} ;
void addCheck(SceneCheck::SPtr check) ;
void removeCheck(SceneCheck::SPtr check) ;

std::map<std::string, std::vector<ChangeSetHookFunction>> m_changesets ;
private:
std::vector<SceneCheck::SPtr> m_checkset ;
};

} // namespace simulation
Expand Down
Loading