Skip to content

Commit

Permalink
Merge pull request #392 from SofaDefrost/addSceneCheckerDuplicate
Browse files Browse the repository at this point in the history
[SofaGraphComponent] Refactor the SceneChecker and add a new SceneChecker to test duplicated names.
  • Loading branch information
damienmarchal authored Sep 15, 2017
2 parents 7e76203 + f01baa5 commit 38412b9
Show file tree
Hide file tree
Showing 8 changed files with 435 additions and 116 deletions.
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
111 changes: 22 additions & 89 deletions modules/SofaGraphComponent/SceneCheckerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <sofa/helper/system/PluginManager.h>
#include <sofa/helper/system/FileRepository.h>

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

Expand All @@ -44,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)
{
msg_info("SceneChecker") << "The 'APIVersion' directive is missing in the current scene. Switching to the default APIVersion level '"<< m_selectedApiLevel <<"' " ;
}
else
std::stringstream tmp;
for(SceneCheck::SPtr& check : m_checkset)
{
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

0 comments on commit 38412b9

Please sign in to comment.