Commit 4a3a86f7 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[CHANGE] - prepared factory and combiners for combination of existing modules.

parent e6a89632
......@@ -543,7 +543,7 @@ void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
// ok, reset the toolbar
// So create a dummy to permanently reserve the space
m_currentCompatiblesToolbar = new WQtCombinerToolbar( this, WCompatiblesList() );
m_currentCompatiblesToolbar = new WQtCombinerToolbar( this, WCombinerTypes::WCompatiblesList() );
}
// optional toolbar break
......
......@@ -37,7 +37,7 @@
#include "WQtCombinerActionList.h"
WQtCombinerActionList::WQtCombinerActionList( QWidget* parent, WIconManager* icons, WCompatiblesList compatibles ):
WQtCombinerActionList::WQtCombinerActionList( QWidget* parent, WIconManager* icons, WCombinerTypes::WCompatiblesList compatibles ):
QList< QAction* >()
{
// These modules will be allowed to be shown.
......@@ -46,7 +46,7 @@ WQtCombinerActionList::WQtCombinerActionList( QWidget* parent, WIconManager* ico
std::vector< std::string > moduleWhiteList = string_utils::tokenize( moduleWhiteListString, "," );
// create an action for each group:
for ( WCompatiblesList::iterator groups = compatibles.begin(); groups != compatibles.end(); ++groups )
for ( WCombinerTypes::WCompatiblesList::iterator groups = compatibles.begin(); groups != compatibles.end(); ++groups )
{
// check current prototype against whitelist
if( moduleWhiteList.size()
......@@ -65,8 +65,8 @@ WQtCombinerActionList::WQtCombinerActionList( QWidget* parent, WIconManager* ico
{
QMenu* groupMenu = new QMenu( parent );
// iterate all the children
for ( WCompatibleCombiners::iterator combiner = ( *groups ).second.begin();
combiner != ( *groups ).second.end(); ++combiner )
for ( WCombinerTypes::WCompatibleCombiners::iterator combiner = ( *groups ).second.begin();
combiner != ( *groups ).second.end(); ++combiner )
{
WQtApplyModuleAction* a = new WQtApplyModuleAction( parent, icons, ( *combiner ), true );
a->setIconVisibleInMenu( true );
......
......@@ -47,7 +47,7 @@ public:
* \param icons the icon manager holding the right icons for all the prototypes
* \param compatibles the list of combiners
*/
WQtCombinerActionList( QWidget* parent, WIconManager* icons, WCompatiblesList compatibles );
WQtCombinerActionList( QWidget* parent, WIconManager* icons, WCombinerTypes::WCompatiblesList compatibles );
/**
* Destructor.
......
......@@ -39,7 +39,7 @@
#include "WQtCombinerToolbar.h"
WQtCombinerToolbar::WQtCombinerToolbar( WMainWindow* parent, WCompatiblesList compatibles )
WQtCombinerToolbar::WQtCombinerToolbar( WMainWindow* parent, WCombinerTypes::WCompatiblesList compatibles )
: QToolBar( "Compatible Modules", parent )
{
// setup toolbar
......
......@@ -44,7 +44,7 @@ public:
* \param parent the parent widget of this widget, i.e. the widget that manages it.
* \param compatibles the list of combiners
*/
explicit WQtCombinerToolbar( WMainWindow* parent, WCompatiblesList compatibles );
explicit WQtCombinerToolbar( WMainWindow* parent, WCombinerTypes::WCompatiblesList compatibles );
/**
* destructor
......
......@@ -728,7 +728,7 @@ WQtCombinerToolbar* WQtDatasetBrowser::createCompatibleButtons( boost::shared_pt
{
// every module may have compatibles: create ribbon menu entry
// NOTE: if module is NULL, getCompatiblePrototypes returns the list of modules without input connector (nav slices and so on)
WCompatiblesList comps = WModuleFactory::getModuleFactory()->getCompatiblePrototypes( module );
WCombinerTypes::WCompatiblesList comps = WModuleFactory::getModuleFactory()->getCompatiblePrototypes( module );
// build the prototype menu
QMenu* m = new QMenu( m_moduleTreeWidget );
......@@ -737,7 +737,11 @@ WQtCombinerToolbar* WQtDatasetBrowser::createCompatibleButtons( boost::shared_pt
m_connectWithPrototypeAction->setMenu( m );
// build the module menu
// TODO(ebaum): do
comps = WKernel::getRunningKernel()->getRootContainer()->getPossibleConnections( module );
m = new QMenu( m_moduleTreeWidget );
m->addActions( WQtCombinerActionList( m, m_mainWindow->getIconManager(), comps ) );
delete( m_connectWithModuleAction->menu() ); // ensure that combiners get free'd
m_connectWithModuleAction->setMenu( m );
// build the disconnect menu
// TODO(ebaum): do
......
......@@ -27,3 +27,8 @@
#include "WModuleCombinerTypes.h"
bool WCombinerTypes::compatiblesSort( WCombinerTypes::WCompatiblesGroup lhs, WCombinerTypes::WCompatiblesGroup rhs )
{
return ( lhs.first->getName() < rhs.first->getName() );
}
......@@ -30,21 +30,34 @@
class WModule;
class WApplyCombiner;
/**
* A list of all combiners in a group.
*/
typedef std::vector< boost::shared_ptr< WApplyCombiner > > WCompatibleCombiners;
/**
* A group of compatible connections to and from a specified module, which is additionally stored in the first element of the pair. This first
* element will never be the module to which the compatible connections have been searched for.
*/
typedef std::pair< boost::shared_ptr< WModule >, WCompatibleCombiners > WCompatiblesGroup;
/**
* This is a list of compatible connection groups, which has been created for a specific module.
*/
typedef std::vector< WCompatiblesGroup > WCompatiblesList;
namespace WCombinerTypes
{
/**
* A list of all combiners in a group.
*/
typedef std::vector< boost::shared_ptr< WApplyCombiner > > WCompatibleCombiners;
/**
* A group of compatible connections to and from a specified module, which is additionally stored in the first element of the pair. This first
* element will never be the module to which the compatible connections have been searched for.
*/
typedef std::pair< boost::shared_ptr< WModule >, WCompatibleCombiners > WCompatiblesGroup;
/**
* This is a list of compatible connection groups, which has been created for a specific module.
*/
typedef std::vector< WCompatiblesGroup > WCompatiblesList;
/**
* Sorting function for sorting the compatibles list. It uses the alphabetical order of the names.
*
* \param lhs the first combiner
* \param rhs the second combiner
*
* \return true if lhs < rhs
*/
bool compatiblesSort( WCompatiblesGroup lhs, WCompatiblesGroup rhs );
}
#endif // WMODULECOMBINERTYPES_H
......@@ -30,20 +30,21 @@
#include <algorithm>
#include <utility>
#include "WModule.h"
#include "WModuleCombiner.h"
#include "exceptions/WModuleUninitialized.h"
#include "exceptions/WModuleAlreadyAssociated.h"
#include "exceptions/WModuleSignalSubscriptionFailed.h"
#include "../common/WLogger.h"
#include "../common/WThreadedRunner.h"
#include "WBatchLoader.h"
#include "WKernel.h"
#include "WModule.h"
#include "WModuleCombiner.h"
#include "WModuleFactory.h"
#include "WModuleTypes.h"
#include "WModuleInputConnector.h"
#include "WModuleOutputConnector.h"
#include "WBatchLoader.h"
#include "WModuleTypes.h"
#include "combiner/WApplyCombiner.h"
#include "combiner/WApplyModuleCombiner.h"
#include "exceptions/WModuleAlreadyAssociated.h"
#include "exceptions/WModuleSignalSubscriptionFailed.h"
#include "exceptions/WModuleUninitialized.h"
#include "../modules/data/WMData.h"
#include "WModuleContainer.h"
......@@ -439,18 +440,29 @@ WModuleContainer::ModuleSharedContainerType::ReadTicket WModuleContainer::getMod
return m_modules.getReadTicket();
}
WCompatiblesList WModuleContainer::getPossibleConnections( boost::shared_ptr< WModule > module )
WCombinerTypes::WCompatiblesList WModuleContainer::getPossibleConnections( boost::shared_ptr< WModule > module )
{
WCompatiblesList complist;
WCombinerTypes::WCompatiblesList complist;
// read lock the container
ModuleSharedContainerType::ReadTicket lock = m_modules.getReadTicket();
// TODO(ebaum): do the same for inputs (module->getInputConnectors())
// handle each module
for( ModuleConstIterator listIter = lock->get().begin(); listIter != lock->get().end(); ++listIter )
{
WCombinerTypes::WCompatibleCombiners lComp = WApplyCombiner::createCombinerList< WApplyModuleCombiner>( module, ( *listIter ) );
if ( lComp.size() != 0 )
{
complist.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
}
}
// sort the compatibles
std::sort( complist.begin(), complist.end(), WCombinerTypes::compatiblesSort );
return complist;
}
......@@ -263,7 +263,7 @@ public:
*
* \return the possible combinations of connectors.
*/
WCompatiblesList getPossibleConnections( boost::shared_ptr< WModule > module );
WCombinerTypes::WCompatiblesList getPossibleConnections( boost::shared_ptr< WModule > module );
protected:
......
......@@ -156,6 +156,18 @@ void WModuleFactory::load()
}
}
bool WModuleFactory::isPrototype( boost::shared_ptr< WModule > module )
{
// for this a read lock is sufficient, gets unlocked if it looses scope
PrototypeSharedContainerType::ReadTicket l = getModuleFactory()->m_prototypes.getReadTicket();
return getModuleFactory()->checkPrototype( module, l );
}
bool WModuleFactory::checkPrototype( boost::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket )
{
return ( ticket->get().count( module ) != 0 );
}
boost::shared_ptr< WModule > WModuleFactory::create( boost::shared_ptr< WModule > prototype )
{
wlog::debug( "ModuleFactory" ) << "Creating new instance of prototype \"" << prototype->getName() << "\".";
......@@ -164,7 +176,7 @@ boost::shared_ptr< WModule > WModuleFactory::create( boost::shared_ptr< WModule
PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket();
// ensure this one is a prototype and nothing else
if ( l->get().count( prototype ) == 0 )
if ( !checkPrototype( prototype, l ) )
{
throw WPrototypeUnknown( "Could not clone module \"" + prototype->getName() + "\" since it is no prototype." );
}
......@@ -238,22 +250,9 @@ WModuleFactory::PrototypeSharedContainerType::ReadTicket WModuleFactory::getProt
return m_prototypes.getReadTicket();
}
/**
* Sorting function for sorting the compatibles list. It uses the alphabetical order of the names.
*
* \param lhs the first combiner
* \param rhs the second combiner
*
* \return true if lhs < rhs
*/
bool compatiblesSort( WCompatiblesGroup lhs, WCompatiblesGroup rhs )
{
return ( lhs.first->getName() < rhs.first->getName() );
}
WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WModule > module )
WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WModule > module )
{
WCompatiblesList compatibles;
WCombinerTypes::WCompatiblesList compatibles;
// for this a read lock is sufficient, gets unlocked if it looses scope
PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket();
......@@ -273,7 +272,7 @@ WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WMo
lComp.push_back( boost::shared_ptr< WApplyCombiner >( new WApplyPrototypeCombiner( module, "", *listIter, "" ) ) );
// add this list
compatibles.push_back( WCompatiblesGroup( ( *listIter ), lComp ) );
compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
}
}
......@@ -283,55 +282,16 @@ WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WMo
return compatibles;
}
// get offered outputs
WModule::OutputConnectorList cons = module->getOutputConnectors();
// return early if we have no output connector, because the modules with no input connector
// are already added at this point.
if( cons.size() == 0 )
{
return compatibles;
}
// go through every prototype
for( PrototypeContainerIteratorType listIter = l->get().begin(); listIter != l->get().end();
++listIter )
{
// get connectors of this prototype
WModule::InputConnectorList pcons = ( *listIter )->getInputConnectors();
// ensure we have 1 connector
if( pcons.size() == 0 )
{
continue;
}
// this list contains all connections for the current module
std::vector< boost::shared_ptr< WApplyCombiner > > lComp;
// iterate connector list, first find all matches of the output connectors with all inputs
for ( WModule::OutputConnectorList::const_iterator outIter = cons.begin(); outIter != cons.end(); ++outIter )
{
// now go through each input iterator of the current prototype
for ( WModule::InputConnectorList::const_iterator inIter = pcons.begin(); inIter != pcons.end(); ++inIter )
{
// compatible?
if ( ( *outIter )->connectable( *inIter ) && ( *inIter )->connectable( *outIter ) )
{
// create a apply-prototype combiner
lComp.push_back( boost::shared_ptr< WApplyCombiner >(
new WApplyPrototypeCombiner( module, ( *outIter )->getName(), *listIter, ( *inIter )->getName() ) )
);
// wlog::debug( "ModuleFactory" ) << ( *outIter )->getCanonicalName() << " -> " << ( *inIter )->getCanonicalName();
}
}
}
WCombinerTypes::WCompatibleCombiners lComp = WApplyCombiner::createCombinerList< WApplyPrototypeCombiner >( module, ( *listIter ) );
// add the group
if ( lComp.size() != 0 )
{
compatibles.push_back( WCompatiblesGroup( ( *listIter ), lComp ) );
compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
}
}
......@@ -339,7 +299,7 @@ WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WMo
l.reset();
// sort the compatibles
std::sort( compatibles.begin(), compatibles.end(), compatiblesSort );
std::sort( compatibles.begin(), compatibles.end(), WCombinerTypes::compatiblesSort );
return compatibles;
}
......
......@@ -154,7 +154,7 @@ public:
*
* \return set of compatible combiners.
*/
WCompatiblesList getCompatiblePrototypes(
WCombinerTypes::WCompatiblesList getCompatiblePrototypes(
boost::shared_ptr< WModule > module = boost::shared_ptr< WModule >()
);
......@@ -166,6 +166,15 @@ public:
*/
static void initializeModule( boost::shared_ptr< WModule > module );
/**
* Checks whether the specified module is a prototype or an instantiated module.
*
* \param module the module to check
*
* \return true if it is a prototype
*/
static bool isPrototype( boost::shared_ptr< WModule > module );
protected:
/**
......@@ -173,6 +182,16 @@ protected:
*/
PrototypeSharedContainerType m_prototypes;
/**
* Checks whether the specified module is a prototype or an instantiated module. Use isPrototype if no ticket acquired yet.
*
* \param module the module to check
* \param ticket ticket which already has read lock.
*
* \return true if it is a prototype
*/
bool checkPrototype( boost::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket );
private:
/**
......
......@@ -34,6 +34,10 @@
#include "../WModule.h"
#include "../WModuleCombiner.h"
#include "../WModuleCombinerTypes.h"
#include "../WModuleInputConnector.h"
#include "../WModuleOutputConnector.h"
/**
* Base class for all combiners which apply one connection between two connectors of two modules.
......@@ -111,6 +115,52 @@ public:
*/
std::string getTargetConnector() const;
/**
* This method creates a list of possible combiners for connections between the specified modules. Both modules can be prototypes.
*
* \param module1 the first module
* \param module2 the second module
*/
template < typename T >
static WCombinerTypes::WCompatibleCombiners createCombinerList( boost::shared_ptr< WModule > module1, boost::shared_ptr< WModule > module2 )
{
// this list contains all connections for the current module with the other one
WCombinerTypes::WCompatibleCombiners lComp;
// get offered outputs
WModule::OutputConnectorList cons = module1->getOutputConnectors();
// get connectors of this prototype
WModule::InputConnectorList pcons = module2->getInputConnectors();
// ensure we have 1 connector
if( ( pcons.size() == 0 ) || ( cons.size() == 0 ) )
{
return lComp;
}
// iterate connector list, first find all matches of the output connectors with all inputs
for ( WModule::OutputConnectorList::const_iterator outIter = cons.begin(); outIter != cons.end(); ++outIter )
{
// now go through each input iterator of the current prototype
for ( WModule::InputConnectorList::const_iterator inIter = pcons.begin(); inIter != pcons.end(); ++inIter )
{
// compatible?
if ( ( *outIter )->connectable( *inIter ) && ( *inIter )->connectable( *outIter ) )
{
// create a apply-prototype combiner
lComp.push_back( boost::shared_ptr< WApplyCombiner >(
new T( module1, ( *outIter )->getName(), module2, ( *inIter )->getName() ) )
);
// wlog::debug( "ModuleFactory" ) << ( *outIter )->getCanonicalName() << " -> " << ( *inIter )->getCanonicalName();
}
}
}
return lComp;
}
protected:
/**
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <iostream>
#include <map>
#include <list>
#include <string>
#include <utility>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include "../WKernel.h"
#include "../WModuleCombiner.h"
#include "../WModuleFactory.h"
#include "../WModuleConnector.h"
#include "../WModule.h"
#include "../WModuleInputConnector.h"
#include "../WModuleOutputConnector.h"
#include "../exceptions/WModuleConnectorNotFound.h"
#include "../../common/WLogger.h"
#include "WApplyModuleCombiner.h"
WApplyModuleCombiner::WApplyModuleCombiner( boost::shared_ptr< WModuleContainer > target,
boost::shared_ptr< WModule > srcModule, std::string srcConnector,
boost::shared_ptr< WModule > targetModule, std::string targetConnector ):
WApplyCombiner( target, srcModule, srcConnector, targetModule, targetConnector )
{
// initialize
}
WApplyModuleCombiner::WApplyModuleCombiner( boost::shared_ptr< WModule > srcModule, std::string srcConnector,
boost::shared_ptr< WModule > targetModule, std::string targetConnector ):
WApplyCombiner( srcModule, srcConnector, targetModule, targetConnector )
{
// initialize
}
WApplyModuleCombiner::~WApplyModuleCombiner()
{
// cleanup
}
void WApplyModuleCombiner::apply()
{
/*// add the target module to the container
m_container->add( targetModule );
// NOTE: here, we assume the src module already to be in the container. If not, connect will fail with an exception -> so no need for a
// separate exception here
// wait for the source module if there is any
if ( m_srcModule ) // specifying a NULL source module causes the combiner to only add the target
{
m_srcModule->isReadyOrCrashed().wait();
if ( m_srcModule->isCrashed()() )
{
wlog::error( "Prototype Combiner" ) << "The source module \"" << m_srcModule->getName() << "\" has crashed. Abort.";
return;
}
}
targetModule->isReadyOrCrashed().wait();
if ( targetModule->isCrashed()() )
{
wlog::error( "Prototype Combiner" ) << "The target module \"" << targetModule->getName() << "\" has crashed. Abort.";
return;
}
// if the target connector is an empty string -> do not connect, just add
if ( m_targetConnector.empty() )
{
return;
}
// and connect them finally:
if ( m_srcModule )
{
targetModule->getInputConnector( m_targetConnector )->connect( m_srcModule->getOutputConnector( m_srcConnector ) );
}*/
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WAPPLYMODULECOMBINER_H
#define WAPPLYMODULECOMBINER_H
#include <list>
#include <map>
#include <string>
#include <utility>
#include <boost/shared_ptr.hpp>
#include "../WModule.h"
#include "WApplyCombiner.h"
/**
* This class combines an existing module with an specified module. The connections to use must be explicitly known.
*/
class WApplyModuleCombiner: public WApplyCombiner
{
public:
/**
* Creates a combiner which sets up the specified module-to-module connection. Specifying a NULL pointer to the srcModule parameter
* causes the combiner to only add the target module without any connections. This is especially useful for modules which do not provide any
* input which must be connected.
*
*