Commit ae4be556 authored by Kasper Marstal's avatar Kasper Marstal

Merge branch 'develop' into SELX-138-stop-ATen-build-if-python-is-not-found

parents 6c041871 a3eeb225
......@@ -72,43 +72,58 @@ main( int ac, char * av[] )
{
selx::Logger::Pointer logger = selx::Logger::New();
typedef std::vector< std::string > VectorOfStringsType;
typedef std::vector< boost::filesystem::path > VectorOfPathsType;
try
{
typedef std::vector< std::string > VectorOfStringsType;
typedef std::vector< boost::filesystem::path > VectorOfPathsType;
boost::filesystem::path logPath;
// default log level
selx::LogLevel logLevel = selx::LogLevel::WRN;
boost::filesystem::path logPath;
// default log level
selx::LogLevel logLevel = selx::LogLevel::WRN;
boost::filesystem::path configurationPath;
VectorOfPathsType configurationPaths;
boost::filesystem::path configurationPath;
VectorOfPathsType configurationPaths;
VectorOfStringsType inputPairs;
VectorOfStringsType outputPairs;
VectorOfStringsType inputPairs;
VectorOfStringsType outputPairs;
boost::program_options::variables_map vm;
try
{
boost::program_options::options_description desc("Allowed options");
desc.add_options()
( "help", "produce help message" )
("conf", boost::program_options::value< VectorOfPathsType >(&configurationPaths)->required()->multitoken(), "Configuration file")
("in", boost::program_options::value< VectorOfStringsType >(&inputPairs)->multitoken(), "Input data: images, labels, meshes, etc. Usage <name>=<path>")
("out", boost::program_options::value< VectorOfStringsType >(&outputPairs)->multitoken(), "Output data: images, labels, meshes, etc. Usage <name>=<path>")
("conf", boost::program_options::value< VectorOfPathsType >(&configurationPaths)->required()->multitoken(), "Configuration file: single or multiple Blueprints [.xml|.json]")
("in", boost::program_options::value< VectorOfStringsType >(&inputPairs)->multitoken(), "Input data: images, labels, meshes, etc. Usage arg: <name>=<path> (or multiple pairs)")
("out", boost::program_options::value< VectorOfStringsType >(&outputPairs)->multitoken(), "Output data: images, labels, meshes, etc. Usage arg: <name>=<path> (or multiple pairs)")
("graphout", boost::program_options::value< boost::filesystem::path >(), "Output Graphviz dot file")
("logfile", boost::program_options::value< boost::filesystem::path >(&logPath), "Log output file")
("loglevel", boost::program_options::value< selx::LogLevel >(&logLevel), "Log level")
("loglevel", boost::program_options::value< selx::LogLevel >(&logLevel), "Log level [off|critical|error|warning|info|debug|trace]")
;
boost::program_options::variables_map vm;
boost::program_options::store(boost::program_options::parse_command_line(ac, av, desc), vm);
boost::program_options::notify(vm);
if( vm.count( "help" ) )
{
std::cout << desc << "\n";
return 0;
}
boost::program_options::notify(vm);
}
catch (std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
std::cerr << "See 'SuperElastix --help' for help" << "\n";
return 1;
}
catch (...)
{
std::cerr << "Unknown error!" << "\n";
return 1;
}
try
{
// optionally, stream to log file
std::ofstream outfile;
if ( vm.count("logfile") )
......@@ -149,7 +164,6 @@ main( int ac, char * av[] )
if( vm.count( "in" ) )
{
logger->Log( selx::LogLevel::INF, "Preparing input data ... ");
int index = 0;
for( const auto & inputPair : inputPairs )
{
VectorOfStringsType nameAndPath;
......@@ -159,15 +173,12 @@ main( int ac, char * av[] )
// since we do not know which reader type we should instantiate for input "name",
// we ask SuperElastix for a reader that matches the type of the source component "name"
logger->Log( selx::LogLevel::INF, "Preparing input " + name + " ..." );
logger->Log( selx::LogLevel::INF, "Preparing input '" + name + "': " + path + " ..." );
selx::AnyFileReader::Pointer reader = superElastixFilter->GetInputFileReader( name );
reader->SetFileName( path );
superElastixFilter->SetInput( name, reader->GetOutput() );
fileReaders.push_back( reader );
logger->Log( selx::LogLevel::INF, "Preparing input " + name + "... Done" );
std::cout << "Input data " << index << " " << name << " : " << path << "\n";
++index;
logger->Log( selx::LogLevel::INF, "Preparing input '" + name + "': " + path + " ... Done" );
}
logger->Log( selx::LogLevel::INF, "Preparing input data ... Done");
}
......@@ -179,7 +190,6 @@ main( int ac, char * av[] )
if( vm.count( "out" ) )
{
logger->Log( selx::LogLevel::INF, "Preparing output data ... ");
int index = 0;
for( const auto & outputPair : outputPairs )
{
VectorOfStringsType nameAndPath;
......@@ -189,16 +199,12 @@ main( int ac, char * av[] )
// since we do not know which writer type we should instantiate for output "name",
// we ask SuperElastix for a writer that matches the type of the sink component "name"
logger->Log( selx::LogLevel::INF, "Preparing output " + name + " ..." );
logger->Log( selx::LogLevel::INF, "Preparing output '" + name + "': " + path + " ..." );
selx::AnyFileWriter::Pointer writer = superElastixFilter->GetOutputFileWriter( name );
//ImageWriter2DType::Pointer writer = ImageWriter2DType::New();
writer->SetFileName( path );
//writer->SetInput(superElastixFilter->GetOutput<Image2DType>(name));
writer->SetInput( superElastixFilter->GetOutput( name ) );
fileWriters.push_back( writer );
logger->Log( selx::LogLevel::INF, "Preparing output " + name + " ... Done" );
++index;
logger->Log( selx::LogLevel::INF, "Preparing output '" + name + "': " + path + " ... Done" );
}
}
else
......@@ -216,14 +222,17 @@ main( int ac, char * av[] )
}
catch( std::exception & e )
{
logger->Log( selx::LogLevel::ERR, "Executing ... Error");
std::cerr << "error: " << e.what() << "\n";
logger->Log( selx::LogLevel::CRT, "Executing ... Error");
logger->Log( selx::LogLevel::CRT, e.what());
std::cerr << e.what();
return 1;
}
catch( ... )
{
logger->Log( selx::LogLevel::ERR, "Executing ... Error");
std::cerr << "Exception of unknown type!\n";
logger->Log( selx::LogLevel::CRT, "Executing ... Error");
logger->Log( selx::LogLevel::CRT, "Exception of unknown type!");
std::cerr << "Exception of unknown type!";
return 1;
}
return 0;
......
......@@ -58,6 +58,7 @@ public:
/* m_Blueprint is initialized in the default constructor */
Blueprint();
~Blueprint();
/** The actual blueprint is a pimpled member variable */
typedef std::unique_ptr< BlueprintImpl > BlueprintImplPointer;
......@@ -86,7 +87,7 @@ public:
//std::unique_ptr<BlueprintImpl> Clone(BlueprintImpl const &other );
// "functional" composition of blueprints is done by adding settings of other to this blueprint. Redefining/overwriting properties is not allowed and returns false.
bool ComposeWith( Blueprint::ConstPointer other );
bool ComposeWith( const Blueprint * other );
// Returns a vector of the Component names at the incoming direction
ComponentNamesType GetInputNames( const ComponentNameType name ) const;
......@@ -103,10 +104,13 @@ public:
void MergeFromFile(const std::string& filename);
void SetLogger( Logger::Pointer logger );
private:
BlueprintImplPointer m_Blueprint;
// The order of the logger and the blueprint matters, since the lifetime of the logger should always exceed that of the blueprint.
Logger::Pointer m_Logger;
BlueprintImplPointer m_BlueprintImpl;
};
}
......
......@@ -24,25 +24,28 @@ namespace selx
{
Blueprint
::Blueprint()
::Blueprint() :
m_Logger( Logger::New() ), // Create default logger which redirects to std::cout
m_BlueprintImpl( new BlueprintImpl( this->m_Logger->GetLoggerImpl() ) )
{
// Create default logger which redirects to std::cout
this->m_Logger = Logger::New();
//TODO: cannot have independent loggers redirecting to cout.
//this->m_Logger->AddStream("cout", std::cout);
//TODO: this seems to affect other instantiated loggers too.
//this->m_Logger->SetLogLevel(selx::LogLevel::INF);
this->m_Blueprint = BlueprintImplPointer( new BlueprintImpl( this->m_Logger->GetLoggerImpl() ) );
}
// This class uses the pimpl idiom and therefore needs to implement the destructor explicitly: Effective Modern C++, Scott Meyers, item 22
Blueprint
::~Blueprint()
{
}
const BlueprintImpl &
Blueprint
::GetBlueprintImpl( void ) const
{
return *this->m_Blueprint;
return *this->m_BlueprintImpl;
}
......@@ -51,7 +54,7 @@ Blueprint
::SetComponent( ComponentNameType name, ParameterMapType parameterMap )
{
this->Modified();
return this->m_Blueprint->SetComponent( name, parameterMap );
return this->m_BlueprintImpl->SetComponent( name, parameterMap );
}
......@@ -59,7 +62,7 @@ Blueprint::ParameterMapType
Blueprint
::GetComponent( ComponentNameType componentName ) const
{
return this->m_Blueprint->GetComponent( componentName );
return this->m_BlueprintImpl->GetComponent( componentName );
}
......@@ -68,14 +71,14 @@ Blueprint
::DeleteComponent( ComponentNameType componentName )
{
this->Modified();
return this->m_Blueprint->DeleteComponent( componentName );
return this->m_BlueprintImpl->DeleteComponent( componentName );
}
Blueprint::ComponentNamesType
Blueprint::GetComponentNames( void ) const
{
return this->m_Blueprint->GetComponentNames();
return this->m_BlueprintImpl->GetComponentNames();
}
......@@ -84,7 +87,7 @@ Blueprint
::SetConnection( ComponentNameType upstream, ComponentNameType downstream, ParameterMapType parameterMap )
{
this->Modified();
return this->m_Blueprint->SetConnection( upstream, downstream, parameterMap );
return this->m_BlueprintImpl->SetConnection( upstream, downstream, parameterMap );
}
......@@ -92,7 +95,7 @@ Blueprint::ParameterMapType
Blueprint
::GetConnection( ComponentNameType upstream, ComponentNameType downstream ) const
{
return this->m_Blueprint->GetConnection( upstream, downstream );
return this->m_BlueprintImpl->GetConnection( upstream, downstream );
}
......@@ -101,7 +104,7 @@ Blueprint
::DeleteConnection( ComponentNameType upstream, ComponentNameType downstream )
{
this->Modified();
return this->m_Blueprint->DeleteConnection( upstream, downstream );
return this->m_BlueprintImpl->DeleteConnection( upstream, downstream );
}
......@@ -109,7 +112,7 @@ bool
Blueprint
::ComponentExists( ComponentNameType componentName ) const
{
return this->m_Blueprint->ComponentExists( componentName );
return this->m_BlueprintImpl->ComponentExists( componentName );
}
......@@ -117,16 +120,16 @@ bool
Blueprint
::ConnectionExists( ComponentNameType upstream, ComponentNameType downstream ) const
{
return this->m_Blueprint->ConnectionExists( upstream, downstream );
return this->m_BlueprintImpl->ConnectionExists( upstream, downstream );
}
bool
Blueprint
::ComposeWith( Blueprint::ConstPointer other)
::ComposeWith( const Blueprint * other)
{
this->Modified();
return this->m_Blueprint->ComposeWith( other->GetBlueprintImpl() );
return this->m_BlueprintImpl->ComposeWith( other->GetBlueprintImpl() );
}
......@@ -134,7 +137,7 @@ Blueprint::ComponentNamesType
Blueprint
::GetOutputNames( const ComponentNameType name ) const
{
return this->m_Blueprint->GetOutputNames( name );
return this->m_BlueprintImpl->GetOutputNames( name );
}
......@@ -142,7 +145,7 @@ Blueprint::ComponentNamesType
Blueprint
::GetInputNames( const ComponentNameType name ) const
{
return this->m_Blueprint->GetInputNames( name );
return this->m_BlueprintImpl->GetInputNames( name );
}
......@@ -150,14 +153,14 @@ void
Blueprint
::Write( const std::string filename )
{
this->m_Blueprint->Write( filename );
this->m_BlueprintImpl->Write( filename );
}
void
Blueprint
::MergeFromFile( const std::string& filename )
{
this->m_Blueprint->MergeFromFile( filename );
this->m_BlueprintImpl->MergeFromFile( filename );
}
void
......@@ -165,7 +168,7 @@ Blueprint
::SetLogger( Logger::Pointer logger )
{
this->m_Logger = logger;
this->m_Blueprint->SetLoggerImpl( logger->GetLoggerImpl() );
this->m_BlueprintImpl->SetLoggerImpl( logger->GetLoggerImpl() );
}
......
......@@ -94,10 +94,6 @@ make_edge_label_writer( ParameterMapType p )
return edge_label_writer< ParameterMapType >( p );
}
// TODO: remove this argumentless constructor
BlueprintImpl::BlueprintImpl( void ) : m_LoggerImpl(&(Logger::New()->GetLoggerImpl()))
{
}
BlueprintImpl::BlueprintImpl( LoggerImpl & loggerImpl ) : m_LoggerImpl(&loggerImpl)
{
......@@ -128,6 +124,7 @@ BlueprintImpl
{
std::stringstream msg;
msg << "BlueprintImpl does not contain component " << name << std::endl;
this->m_LoggerImpl->Log(LogLevel::CRT, msg.str());
throw std::runtime_error( msg.str() );
}
......@@ -168,6 +165,7 @@ BlueprintImpl
{
if( !this->ComponentExists( upstream ) || !this->ComponentExists( downstream ) )
{
this->m_LoggerImpl->Log(LogLevel::WRN, "Setting a connection between components '{}' and '{}' failed: one or more components do not exist");
return false;
}
......@@ -391,6 +389,7 @@ BlueprintImpl
// This function is part of the internal API and should fail hard if we use it incorrectly
if( !this->ConnectionExists( upstream, downstream ) )
{
this->m_LoggerImpl->Log(LogLevel::CRT, "BlueprintImpl does not contain connection from component {} to {}.", upstream, downstream );
throw std::runtime_error( "BlueprintImpl does not contain connection from component " + upstream + " to " + downstream );
}
......@@ -538,7 +537,7 @@ BlueprintImpl::FromPropertyTree(const PropertyTreeType & pt)
std::string connectionName = v.second.data();
if (connectionName != "")
{
this->m_LoggerImpl->Log(LogLevel::INF, "Found {0}, but connection names are ignored.", connectionName);
this->m_LoggerImpl->Log(LogLevel::TRC, "Found {0}, but connection names are ignored.", connectionName);
}
std::string outName;
std::string inName;
......@@ -654,7 +653,7 @@ BlueprintImpl::MergeProperties(const PropertyTreeType & pt)
std::string connectionName = v.second.data();
if (connectionName != "")
{
this->m_LoggerImpl->Log(LogLevel::INF, "Found {0}, but connection names are ignored.", connectionName);
this->m_LoggerImpl->Log(LogLevel::TRC, "Found {0}, but connection names are ignored.", connectionName);
}
std::string outName;
std::string inName;
......
......@@ -99,9 +99,6 @@ public:
typedef boost::graph_traits< GraphType >::out_edge_iterator OutputIteratorType;
typedef std::pair< OutputIteratorType, OutputIteratorType > OutputIteratorPairType;
// TODO: remove this argumentless constructor
BlueprintImpl();
BlueprintImpl( LoggerImpl & loggerImpl);
......
......@@ -48,8 +48,7 @@ public:
TEST_F( BlueprintTest, SetGetDeleteComponent )
{
std::unique_ptr< BlueprintImpl > blueprint;
EXPECT_NO_THROW( blueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto blueprint = Blueprint::New();
bool success0;
EXPECT_NO_THROW( success0 = blueprint->SetComponent( "MyComponentName", parameterMap ) );
......@@ -80,8 +79,7 @@ TEST_F( BlueprintTest, BlueprintObjectSetGetDeleteComponent )
TEST_F( BlueprintTest, SetGetDeleteConnection )
{
std::unique_ptr< BlueprintImpl > blueprint;
EXPECT_NO_THROW( blueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto blueprint = Blueprint::New();
blueprint->SetComponent( "Component0", parameterMap );
blueprint->SetComponent( "Component1", parameterMap );
......@@ -126,12 +124,13 @@ TEST_F( BlueprintTest, SetGetDeleteConnection )
TEST_F( BlueprintTest, CopyConstuctor )
{
std::unique_ptr< BlueprintImpl > baseBlueprint;
EXPECT_NO_THROW( baseBlueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto baseBlueprint = Blueprint::New();
baseBlueprint->SetComponent( "Component0", { { "OperationType", { "Transform" } } } );
auto baseBlueprintImpl = baseBlueprint->GetBlueprintImpl();
std::unique_ptr< BlueprintImpl > clonedBaseBlueprint;
EXPECT_NO_THROW( clonedBaseBlueprint = std::make_unique< BlueprintImpl >( *baseBlueprint.get() ) );
EXPECT_NO_THROW( clonedBaseBlueprint = std::make_unique< BlueprintImpl >( baseBlueprintImpl ) );
EXPECT_NO_THROW( clonedBaseBlueprint->SetComponent( "Component1", { { "OperationType", { "Source" } }, { "Dimensionality", { "3" } } } ) );
......@@ -144,48 +143,43 @@ TEST_F( BlueprintTest, CopyConstuctor )
TEST_F( BlueprintTest, Compose )
{
std::unique_ptr< BlueprintImpl > baseBlueprint;
EXPECT_NO_THROW( baseBlueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto baseBlueprint = Blueprint::New();
baseBlueprint->SetComponent( "Component0", { { "OperationType", { "Transform" } } } );
baseBlueprint->SetComponent( "Component1", { { "OperationType", { "Source" } }, { "Dimensionality", { "3" } } } );
// compose-in a new 3rd component Component2
std::unique_ptr< BlueprintImpl > nonConflictingBlueprint0;
EXPECT_NO_THROW( nonConflictingBlueprint0 = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto nonConflictingBlueprint0 = Blueprint::New();
nonConflictingBlueprint0->SetComponent( "Component2", { { "OperationType", { "Sink" } } } );
EXPECT_TRUE( baseBlueprint->ComposeWith( *nonConflictingBlueprint0 ) );
EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint0 ) );
EXPECT_STREQ( "Sink", baseBlueprint->GetComponent( "Component2" )[ "OperationType" ][ 0 ].c_str() );
// compose-in additional properties of Component0 and Component1
std::unique_ptr< BlueprintImpl > nonConflictingBlueprint1;
EXPECT_NO_THROW( nonConflictingBlueprint1 = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto nonConflictingBlueprint1 = Blueprint::New();
nonConflictingBlueprint1->SetComponent( "Component0", { { "TranformationGroup", { "Diffeomorphic" } }, { "PixelType", { "float" } } } );
nonConflictingBlueprint1->SetComponent( "Component1", { { "NameOfClass", { "ImageSourceClass" } } } );
EXPECT_TRUE( baseBlueprint->ComposeWith( *nonConflictingBlueprint1 ) );
EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint1 ) );
EXPECT_STREQ( "Transform", baseBlueprint->GetComponent( "Component0" )[ "OperationType" ][ 0 ].c_str() );
EXPECT_STREQ( "Diffeomorphic", baseBlueprint->GetComponent( "Component0" )[ "TranformationGroup" ][ 0 ].c_str() );
EXPECT_STREQ( "ImageSourceClass", baseBlueprint->GetComponent( "Component1" )[ "NameOfClass" ][ 0 ].c_str() );
// compose-in existing component with existing property key, but equal property value(s). Nothing happens actually (i.e. idempotency)
std::unique_ptr< BlueprintImpl > nonConflictingBlueprint2;
EXPECT_NO_THROW( nonConflictingBlueprint2 = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto nonConflictingBlueprint2 = Blueprint::New();
nonConflictingBlueprint2->SetComponent( "Component0", { { "PixelType", { "float" } } } );
EXPECT_TRUE( baseBlueprint->ComposeWith( *nonConflictingBlueprint2 ) );
EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint2 ) );
// trying to overwrite properties fails
std::unique_ptr< BlueprintImpl > conflictingBlueprint0;
EXPECT_NO_THROW( conflictingBlueprint0 = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
auto conflictingBlueprint0 = Blueprint::New();
conflictingBlueprint0->SetComponent( "Component1", { { "Dimensionality", { "2" } }, { "InternalComputationValueType", { "float" } } } );
// Compose fails and returns false
EXPECT_FALSE( baseBlueprint->ComposeWith( *conflictingBlueprint0 ) );
EXPECT_FALSE( baseBlueprint->ComposeWith( conflictingBlueprint0 ) );
//baseBlueprint should not have been altered by a failing compose operation
EXPECT_STREQ( "3", baseBlueprint->GetComponent( "Component1" )[ "Dimensionality" ][ 0 ].c_str() );
......
......@@ -58,7 +58,7 @@ NetworkBuilder< ComponentList >::Configure()
this->ApplyComponentConfiguration();
auto nonUniqueComponentNames = this->GetNonUniqueComponentNames();
this->m_Logger.Log( LogLevel::INF,
"Applying component criteria ... Done. {0:d} out of {1:d} components was uniquely selected.",
"Applying component criteria ... Done. {0:d} out of {1:d} components were uniquely selected.",
m_Blueprint.GetComponentNames().size()-nonUniqueComponentNames.size(),
m_Blueprint.GetComponentNames().size() );
......@@ -66,18 +66,17 @@ NetworkBuilder< ComponentList >::Configure()
this->ApplyConnectionConfiguration();
nonUniqueComponentNames = this->GetNonUniqueComponentNames();
this->m_Logger.Log( LogLevel::INF,
"Applying connection criteria ... Done. {0:d} out of {1:d} components was uniquely selected.",
"Applying connection criteria ... Done. {0:d} out of {1:d} components were uniquely selected.",
m_Blueprint.GetComponentNames().size()-nonUniqueComponentNames.size(),
m_Blueprint.GetComponentNames().size() );
if( nonUniqueComponentNames.size() > 0 )
{
this->m_Logger.Log( LogLevel::INF, "{0} components have unsatisfied connections.", nonUniqueComponentNames.size() );
this->m_Logger.Log( LogLevel::INF, "Performing handshakes between unique and non-unique component(s) ..." );
this->PropagateConnectionsWithUniqueComponents();
nonUniqueComponentNames = this->GetNonUniqueComponentNames();
this->m_Logger.Log( LogLevel::INF,
"Performing handshakes between unique and non-unique component(s) ... Done. {0:d} out of {1:d} components was uniquely selected.",
"Performing handshakes between unique and non-unique component(s) ... Done. {0:d} out of {1:d} components were uniquely selected.",
m_Blueprint.GetComponentNames().size()-nonUniqueComponentNames.size(),
m_Blueprint.GetComponentNames().size() );
}
......@@ -151,7 +150,7 @@ NetworkBuilder< ComponentList >::ApplyComponentConfiguration()
currentComponentSelector->AddCriterion( criterion );
this->m_Logger.Log( LogLevel::DBG,
"Finding component for {0}: {1} component(s) satisfies {2} equal {3} and previous criteria.",
"Finding component for '{0}': {1} component(s) satisfies {{ '{2}' : '{3}' }} and previous criteria.",
componentName,
currentComponentSelector->NumberOfComponents(),
criterion.first,
......@@ -189,7 +188,7 @@ NetworkBuilder< ComponentList >::ApplyConnectionConfiguration()
{
BlueprintImpl::ParameterMapType connectionProperties = this->m_Blueprint.GetConnection( providingComponentName, acceptingComponentName );
// TODO: Is there a more elegant alternative to manual conversion between types?
// TODO: #110
ComponentBase::InterfaceCriteriaType interfaceCriteria;
for( const auto& connectionProperty : connectionProperties )
{
......@@ -200,16 +199,18 @@ NetworkBuilder< ComponentList >::ApplyConnectionConfiguration()
}
this->m_ComponentSelectorContainer[ providingComponentName ]->AddProvidingInterfaceCriteria( interfaceCriteria );
this->m_ComponentSelectorContainer[ acceptingComponentName ]->AddAcceptingInterfaceCriteria( interfaceCriteria );
this->m_Logger.Log(LogLevel::DBG,
"Finding component for '{0}': {1} component(s) satisfies 'ProvidingInterface' {2} and previous criteria.",
providingComponentName,
this->m_ComponentSelectorContainer[providingComponentName]->NumberOfComponents(),
this->m_Logger << interfaceCriteria );
if( !interfaceCriteria.empty() )
{
this->m_Logger.Log( LogLevel::DBG,
"{0} can connect to {1} via {2}.",
providingComponentName,
acceptingComponentName,
this->m_Logger << interfaceCriteria );
}
this->m_ComponentSelectorContainer[ acceptingComponentName ]->AddAcceptingInterfaceCriteria( interfaceCriteria );
this->m_Logger.Log(LogLevel::DBG,
"Finding component for '{0}': {1} component(s) satisfies 'AcceptingInterface' {2} and previous criteria.",
acceptingComponentName,
this->m_ComponentSelectorContainer[acceptingComponentName]->NumberOfComponents(),
this->m_Logger << interfaceCriteria );
if( this->m_ComponentSelectorContainer[ acceptingComponentName ]->NumberOfComponents() == 0 )
{
......@@ -242,17 +243,17 @@ NetworkBuilder< ComponentList >::PropagateConnectionsWithUniqueComponents()
{
anySelectionNarrowed = false;
auto nonUniqueComponentNames = this->GetNonUniqueComponentNames();
for( auto const & providingComponentName : nonUniqueComponentNames )
for( auto const & componentName : nonUniqueComponentNames )
{
// check all components that accept from component "providingComponentName"
for( auto const & acceptingComponentName : this->m_Blueprint.GetOutputNames( providingComponentName ) )
// check all components that accept from component "componentName"
for( auto const & acceptingComponentName : this->m_Blueprint.GetOutputNames( componentName ) )
{
// if the accepting component is also not uniquely selected, we do not try to check all valid combinations, since this would make the handshake logic too complicated
if( std::find( nonUniqueComponentNames.begin(), nonUniqueComponentNames.end(), acceptingComponentName ) == nonUniqueComponentNames.end() )
{
BlueprintImpl::ParameterMapType connectionProperties = this->m_Blueprint.GetConnection( providingComponentName, acceptingComponentName );
BlueprintImpl::ParameterMapType connectionProperties = this->m_Blueprint.GetConnection( componentName, acceptingComponentName );
// TODO: Is there a more elegant alternative to manual conversion between types?