00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <iostream>
00026 #include <map>
00027 #include <set>
00028 #include <list>
00029 #include <string>
00030 #include <utility>
00031
00032 #include <boost/regex.hpp>
00033 #include <boost/lexical_cast.hpp>
00034
00035 #include "../WKernel.h"
00036 #include "../WModuleCombiner.h"
00037 #include "../WModuleFactory.h"
00038 #include "../WModuleConnector.h"
00039 #include "../WModule.h"
00040 #include "../WDataModule.h"
00041 #include "../WModuleInputConnector.h"
00042 #include "../WModuleOutputConnector.h"
00043 #include "../exceptions/WModuleConnectorNotFound.h"
00044
00045 #include "../../common/exceptions/WFileNotFound.h"
00046 #include "../../common/WProperties.h"
00047 #include "../../common/WPropertyBase.h"
00048 #include "../../common/WPropertyVariable.h"
00049 #include "../../common/WPropertyTypes.h"
00050 #include "../../common/WLogger.h"
00051 #include "../../common/math/linearAlgebra/WLinearAlgebra.h"
00052
00053 #include "WModuleProjectFileCombiner.h"
00054
00055 WModuleProjectFileCombiner::WModuleProjectFileCombiner( boost::shared_ptr< WModuleContainer > target ):
00056 WModuleCombiner( target ),
00057 WProjectFileIO()
00058 {
00059 }
00060
00061 WModuleProjectFileCombiner::WModuleProjectFileCombiner():
00062 WModuleCombiner( WKernel::getRunningKernel()->getRootContainer() ),
00063 WProjectFileIO()
00064 {
00065 }
00066
00067 WModuleProjectFileCombiner::~WModuleProjectFileCombiner()
00068 {
00069
00070 }
00071
00072 bool WModuleProjectFileCombiner::parse( std::string line, unsigned int lineNumber )
00073 {
00074
00075 static const boost::regex modRe( "^ *MODULE:([0-9]*):(.*)$" );
00076 static const boost::regex dataRe( "^ *DATA:([0-9]*):(.*)$" );
00077 static const boost::regex conRe( "^ *CONNECTION:\\(([0-9]*),(.*)\\)->\\(([0-9]*),(.*)\\)$" );
00078 static const boost::regex propRe( "^ *PROPERTY:\\(([0-9]*),(.*)\\)=(.*)$" );
00079
00080 boost::smatch matches;
00081 if( boost::regex_match( line, matches, modRe ) )
00082 {
00083
00084
00085
00086
00087 wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Module \"" << matches[2] << "\" with ID " << matches[1];
00088
00089
00090 boost::shared_ptr< WModule > proto = WModuleFactory::getModuleFactory()-> isPrototypeAvailable( matches[2] );
00091
00092
00093 if( !proto )
00094 {
00095 wlog::error( "Project Loader" ) << "There is no prototype available for module \"" << matches[2] << "\". Skipping.";
00096 }
00097 else if( proto->getType() == MODULE_DATA )
00098 {
00099 wlog::error( "Project Loader" ) << "Data modules are not allowed to be specified in a \"MODULE\" Statement." <<
00100 " Use the \"DATA\" statement instead. Skipping.";
00101 }
00102 else
00103 {
00104 boost::shared_ptr< WModule > module = WModuleFactory::getModuleFactory()->create( proto );
00105 m_modules.insert( ModuleID( boost::lexical_cast< unsigned int >( matches[1] ), module ) );
00106 }
00107 }
00108 else if( boost::regex_match( line, matches, dataRe ) )
00109 {
00110
00111
00112
00113 wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Data \"" << matches[2] << "\" with ID " << matches[1];
00114
00115
00116 boost::shared_ptr< WModule > proto = WModuleFactory::getModuleFactory()-> isPrototypeAvailable( "Data Module" );
00117 if( !proto )
00118 {
00119 wlog::error( "Project Loader" ) << "There is no prototype available for module \"" << "Data Module" << "\"."
00120 << " This should not happen!. Skipping.";
00121 }
00122 else
00123 {
00124 std::string parameter = std::string( matches[2] );
00125 boost::shared_ptr< WModule > module = WModuleFactory::getModuleFactory()->create( proto );
00126 if( parameter.empty() )
00127 {
00128 wlog::error( "Project Loader" ) << "Data modules need an additional filename parameter. Skipping.";
00129 }
00130 else
00131 {
00132 boost::shared_static_cast< WDataModule >( module )->setFilename( parameter );
00133 m_modules.insert( ModuleID( boost::lexical_cast< unsigned int >( matches[1] ), module ) );
00134 }
00135 }
00136 }
00137 else if( boost::regex_match( line, matches, conRe ) )
00138 {
00139
00140
00141
00142
00143 wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Connection between \"" << matches[2] << "\" of module "
00144 << matches[1] << " and \"" << matches[4] << "\" of module " << matches[3] << ".";
00145
00146
00147 m_connections.push_back( Connection( Connector( boost::lexical_cast< unsigned int >( matches[1] ), matches[2] ),
00148 Connector( boost::lexical_cast< unsigned int >( matches[3] ), matches[4] ) ) );
00149 }
00150 else if( boost::regex_match( line, matches, propRe ) )
00151 {
00152
00153
00154
00155
00156
00157 wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Property \"" << matches[2] << "\" of module " << matches[1]
00158 << " set to " << matches[3];
00159
00160 m_properties.push_back( PropertyValue( Property( boost::lexical_cast< unsigned int >( matches[1] ), matches[2] ), matches[3] ) );
00161 }
00162 else
00163 {
00164 return false;
00165 }
00166
00167 return true;
00168 }
00169
00170 void WModuleProjectFileCombiner::apply()
00171 {
00172
00173 for( std::map< unsigned int, boost::shared_ptr< WModule > >::const_iterator iter = m_modules.begin(); iter != m_modules.end(); ++iter )
00174 {
00175 m_container->add( ( *iter ).second );
00176 }
00177
00178
00179
00180 for( std::map< unsigned int, boost::shared_ptr< WModule > >::iterator iter = m_modules.begin(); iter != m_modules.end(); ++iter )
00181 {
00182 ( *iter ).second->isReadyOrCrashed().wait();
00183
00184
00185 if( ( *iter ).second->isCrashed()() )
00186 {
00187 wlog::warn( "Project Loader" ) << "In the module with ID "
00188 << ( *iter ).first
00189 << " a problem occurred. Connections and properties relating to this"
00190 << " module will fail.";
00191 m_modules.erase( iter );
00192 }
00193 }
00194
00195
00196 for( std::list< PropertyValue >::const_iterator iter = m_properties.begin(); iter != m_properties.end(); ++iter )
00197 {
00198
00199 if( !m_modules.count( ( *iter ).first.first ) )
00200 {
00201 wlog::error( "Project Loader" ) << "There is no module with ID \"" << ( *iter ).first.first << "\" to set the property \"" <<
00202 ( *iter ).first.second << "\" for. Skipping.";
00203 continue;
00204 }
00205 boost::shared_ptr< WModule > m = m_modules[ ( *iter ).first.first ];
00206
00207
00208 boost::shared_ptr< WPropertyBase > prop = m->getProperties()->findProperty( ( *iter ).first.second );
00209 if( !prop )
00210 {
00211 wlog::error( "Project Loader" ) << "The module \"" << m->getName() << "\" has no property named \"" <<
00212 ( *iter ).first.second << "\". Skipping.";
00213 continue;
00214 }
00215 else
00216 {
00217 if( prop->getPurpose() != PV_PURPOSE_INFORMATION )
00218 {
00219
00220 bool result = prop->setAsString( ( *iter ).second );
00221 if( !result )
00222 {
00223 wlog::error( "Project Loader" ) << "Failed to set property " << ( *iter ).first.second << " in module \"" <<
00224 m->getName() << "\".";
00225 }
00226 }
00227 else
00228 {
00229 wlog::error( "Project Loader" ) << "The module \"" << m->getName() << "\" has a property named \"" <<
00230 ( *iter ).first.second << "\" which is an INFORMATION property. Skipping.";
00231 }
00232 }
00233 }
00234
00235
00236 for( std::list< Connection >::const_iterator iter = m_connections.begin(); iter != m_connections.end(); ++iter )
00237 {
00238
00239 Connector c1 = ( *iter ).first;
00240 Connector c2 = ( *iter ).second;
00241
00242
00243
00244 boost::shared_ptr< WModule > m1;
00245 if( !m_modules.count( c1.first ) )
00246 {
00247 wlog::error( "Project Loader" ) << "There is no module with ID \"" << c1.first << "\" for the connection "
00248 << "(" << c1.first << "," << c1.second << ")->(" << c2.first << "," << c2.second << "). Skipping.";
00249
00250 continue;
00251 }
00252 m1 = m_modules[ c1.first ];
00253
00254 boost::shared_ptr< WModule > m2;
00255 if( !m_modules.count( c2.first ) )
00256 {
00257 wlog::error( "Project Loader" ) << "There is no module with ID \"" << c2.first << "\" for the connection "
00258 << "(" << c1.first << "," << c1.second << ")->(" << c2.first << "," << c2.second << "). Skipping.";
00259
00260 continue;
00261 }
00262 m2 = m_modules[ c2.first ];
00263
00264
00265
00266
00267 boost::shared_ptr< WModuleOutputConnector > con1;
00268 try
00269 {
00270 con1 = m1->getOutputConnector( c1.second );
00271 }
00272 catch( const WModuleConnectorNotFound& e )
00273 {
00274 wlog::error( "Project Loader" ) << "There is no output connector \"" << c1.second << "\" in module \"" << m1->getName() << "\"";
00275 continue;
00276 }
00277 boost::shared_ptr< WModuleInputConnector > con2;
00278 try
00279 {
00280 con2 = m2->getInputConnector( c2.second );
00281 }
00282 catch( const WModuleConnectorNotFound& e )
00283 {
00284 wlog::error( "Project Loader" ) << "There is no input connector \"" << c2.second << "\" in module \"" << m2->getName() << "\"";
00285 continue;
00286 }
00287
00288
00289 try
00290 {
00291 con1->connect( con2 );
00292 }
00293 catch( const WException& e )
00294 {
00295 wlog::error( "Project Loader" ) << "Connection " << "(" << c1.first << "," << c1.second << ")->(" << c2.first << "," << c2.second <<
00296 ") could not be created. Incompatible connectors?. Skipping.";
00297 continue;
00298 }
00299 }
00300
00301
00302 m_modules.clear();
00303 m_connections.clear();
00304 m_properties.clear();
00305 }
00306
00307 void WModuleProjectFileCombiner::done()
00308 {
00309 apply();
00310 }
00311
00312 void WModuleProjectFileCombiner::printProperties( std::ostream& output, boost::shared_ptr< WProperties > props, std::string indent,
00313 std::string prefix, unsigned int module )
00314 {
00315
00316 WProperties::PropertySharedContainerType::ReadTicket l = props->getProperties();
00317
00318 output << indent << "// Property Group: " << props->getName() << std::endl;
00319
00320
00321 for( WProperties::PropertyConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
00322 {
00323
00324 if( ( *iter )->getPurpose () == PV_PURPOSE_INFORMATION )
00325 {
00326 continue;
00327 }
00328 if( ( *iter )->getType() != PV_GROUP )
00329 {
00330 output << indent + " " << "PROPERTY:(" << module << "," << prefix + ( *iter )->getName() << ")="
00331 << ( *iter )->getAsString() << std::endl;
00332 }
00333 else
00334 {
00335
00336 if( prefix.empty() )
00337 {
00338 printProperties( output, ( *iter )->toPropGroup(), indent + " ", ( *iter )->getName() + "/", module );
00339 }
00340 else
00341 {
00342 printProperties( output, ( *iter )->toPropGroup(), indent + " ", prefix + ( *iter )->getName() + "/", module );
00343 }
00344 }
00345 }
00346
00347 output << indent << "// Property Group END: " << props->getName() << std::endl;
00348 }
00349
00350 void WModuleProjectFileCombiner::save( std::ostream& output )
00351 {
00352
00353 WModuleContainer::ModuleSharedContainerType::ReadTicket container = WKernel::getRunningKernel()->getRootContainer()->getModules();
00354
00355 std::map< boost::shared_ptr< WModule >, unsigned int > moduleToIDMap;
00356
00357 output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00358 "// Modules and Properties" << std::endl <<
00359 "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00360 std::endl;
00361
00362
00363 unsigned int i = 0;
00364 for( WModuleContainer::ModuleConstIterator iter = container->get().begin(); iter != container->get().end(); ++iter )
00365 {
00366
00367 moduleToIDMap[ ( *iter ) ] = i;
00368
00369
00370 if( ( *iter )->getType() == MODULE_DATA )
00371 {
00372 output << "DATA:" << i << ":" << boost::shared_static_cast< WDataModule >( ( *iter ) )->getFilename() << std::endl;
00373 }
00374 else
00375 {
00376 output << "MODULE:" << i << ":" << ( *iter )->getName() << std::endl;
00377 }
00378
00379
00380 printProperties( output, ( *iter )->getProperties(), "", "", i );
00381
00382
00383 output << std::endl;
00384 ++i;
00385 }
00386
00387
00388 output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00389 "// Connections" << std::endl <<
00390 "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00391 std::endl;
00392
00393
00394
00395 for( WModuleContainer::ModuleConstIterator iter = container->get().begin(); iter != container->get().end(); ++iter )
00396 {
00397
00398 const WModule::OutputConnectorList& outs = ( *iter )->getOutputConnectors();
00399 for( WModule::OutputConnectorList::const_iterator citer = outs.begin(); citer != outs.end(); ++citer )
00400 {
00401
00402
00403 boost::unique_lock<boost::shared_mutex> lock( ( *citer )->m_connectionListLock );
00404 for( std::set<boost::shared_ptr<WModuleConnector> >::const_iterator iciter = ( *citer )->m_connected.begin();
00405 iciter != ( *citer )->m_connected.end(); ++iciter )
00406 {
00407
00408 boost::shared_ptr< WModule > theOtherModule = ( *iciter )->m_module.lock();
00409 output << "CONNECTION:(" << moduleToIDMap[ ( *iter ) ] << "," << ( *citer )->getName() << ")->(" <<
00410 moduleToIDMap[ theOtherModule ] << "," << ( *iciter )->getName() << ")" << std::endl;
00411 }
00412 lock.unlock();
00413 }
00414 }
00415 }
00416