ParsedStateMachine.cpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Tue Jul 20 17:32:42 CEST 2004  ParsedStateMachine.cxx
00003 
00004                         ParsedStateMachine.cxx -  description
00005                            -------------------
00006     begin                : Tue July 20 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place,                                    *
00024  *   Suite 330, Boston, MA  02111-1307  USA                                *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #include "ParsedStateMachine.hpp"
00029 #include "DataSource.hpp"
00030 #include "ExecutionEngine.hpp"
00031 #include "StateDescription.hpp"
00032 
00033 #include "TaskObject.hpp"
00034 #include "StateMachineTask.hpp"
00035 #include <cassert>
00036 
00037 #include <boost/lambda/lambda.hpp>
00038 
00039 namespace RTT {
00040     using namespace detail;
00041     using namespace std;
00042     using namespace boost::lambda;
00043     using boost::tuples::get;
00052     ParsedStateMachinePtr ParsedStateMachine::copy( std::map<const DataSourceBase*, DataSourceBase*>& replacements, bool instantiate ) const
00053     {
00054         /* Recursive copy :
00055          * First copy this SC, then its child SC's
00056          */
00057         std::map<const StateInterface*, StateInterface*> statemapping;
00058         ParsedStateMachinePtr ret(new ParsedStateMachine());
00059         ret->_text = this->_text;
00060         ret->setName( this->_name, false);
00061 
00062         if (instantiate)
00063             Logger::log() <<Logger::Debug <<"Creating an instance of "<< this->_name << Logger::endl;
00064 
00065         // First copy the task such that commands and attributes can be correctly
00066         // copied. This also sets the EventProcessor for the SM.
00067         ret->setTaskObject( this->object->copy(ret, replacements, instantiate) );
00068 
00069         // the parameters of the SC, similar to FunctionGraph's Arguments.
00070         for ( VisibleWritableValuesMap::const_iterator i = parametervalues.begin();
00071               i != parametervalues.end(); ++i )
00072         {
00073             // What is sure, is that each param
00074             // must also be in the attributerepository.
00075             assert( ret->getTaskObject()->attributes()->getValue( i->first ) );
00076             ret->parametervalues[i->first] = ret->getTaskObject()->attributes()->getValue( i->first );
00077         }
00078 
00079         //**********************
00080         // TODO add copy method to StateMachine itself where all stuff below belongs :
00081         // but, not so easy since copy makes new instance...
00082         for ( ChildList::const_iterator i = getChildren().begin(); i != getChildren().end(); ++i )
00083         {
00084             // copy the submachines....
00085             assert( dynamic_cast<ParsedStateMachine*>( i->get() ) == static_cast<ParsedStateMachine*>( i->get() ));
00086             ParsedStateMachine* oldmachine = static_cast<ParsedStateMachine*>( i->get() );
00087             ParsedStateMachinePtr newmachine(oldmachine->copy( replacements, instantiate )); 
00088             // I would think that providing 'instantiate' would not hurt...
00089             // XXX? previously, the instantiate flag was not given to copy, does it now break apps ?
00090 
00091             ret->addChild( newmachine ); // also copy tree info to StateMachine !
00092             newmachine->setParent( ret );
00093         }
00094 
00095         // Copy the InitCommand :
00096         if (this->getInitCommand()) {
00097             ret->setInitCommand( this->getInitCommand()->copy(replacements) );
00098             // test :
00099             //ret->getInitCommand()->execute();
00100         } 
00101 
00102         // First make a copy of all states.  All states are either
00103         // known by their name or by a transition from or to them...
00104         for ( TransitionMap::const_iterator i = stateMap.begin(); i != stateMap.end(); ++i )
00105         {
00106             if( statemapping.find( i->first ) == statemapping.end() ) {
00107                 StateInterface* cpy = i->first->copy( replacements );
00108                 ret->addState( cpy );
00109                 statemapping[i->first] = cpy;
00110             }
00111         }
00112 
00113         // next, copy the transitions
00114         for ( TransitionMap::const_iterator i = stateMap.begin(); i != stateMap.end(); ++i )
00115         {
00116             assert( statemapping.find( i->first ) != statemapping.end() );
00117             StateInterface* fromState = statemapping[i->first];
00118             for ( TransList::const_iterator j = i->second.begin(); j != i->second.end(); ++j )
00119             {
00120                 ConditionInterface* condition = j->get<0>()->copy( replacements );
00121                 assert( statemapping.find( j->get<1>() ) != statemapping.end() );
00122                 StateInterface* toState = statemapping[j->get<1>()];
00123                 int rank = j->get<2>();
00124                 int line = j->get<3>();
00125                 boost::shared_ptr<ProgramInterface> transprog( j->get<4>() );
00126                 if (transprog)
00127                     transprog.reset( j->get<4>()->copy(replacements) );
00128                 ret->transitionSet(fromState, toState, condition, transprog, rank, line );
00129             }
00130         }
00131 
00132         // next, copy/recreate the events
00133         for ( EventMap::const_iterator i = eventMap.begin(); i != eventMap.end(); ++i )
00134         {
00135             assert( statemapping.find( i->first ) != statemapping.end() );
00136             StateInterface* fromState = statemapping[i->first];
00137             for ( EventList::const_iterator j = i->second.begin(); j != i->second.end(); ++j )
00138             {
00139                 EventService* es = j->get<0>();
00140                 string ename = j->get<1>();
00141                 vector<DataSourceBase::shared_ptr> origargs( j->get<2>() );
00142                 vector<DataSourceBase::shared_ptr> newargs;
00143                 for ( vector<DataSourceBase::shared_ptr>::const_iterator vit = origargs.begin();
00144                       vit != origargs.end(); ++vit)
00145                     newargs.push_back( (*vit)->copy(replacements) );
00146                 StateInterface* toState = statemapping[j->get<3>()];
00147                 ConditionInterface* condition = j->get<4>()->copy( replacements );
00148                 ProgramInterfacePtr tprog;
00149                 ProgramInterfacePtr tgraph( j->get<5>() );
00150                 if (tgraph)
00151                     tprog.reset( tgraph->copy(replacements) );
00152                 StateInterface* elseState = statemapping[j->get<7>()];
00153                 ProgramInterfacePtr eprog;
00154                 ProgramInterfacePtr egraph( j->get<8>() );
00155                 if (egraph)
00156                     eprog.reset( egraph->copy(replacements) );
00157 #ifndef NDEBUG
00158                 bool eresult =
00159 #endif                    
00160                     ret->createEventTransition(es, ename, newargs, fromState, toState, condition, tprog, elseState, eprog );
00161                 assert( eresult );
00162             }
00163         }
00164 
00165         // finally, copy the preconditions
00166         for ( PreConditionMap::const_iterator i = precondMap.begin(); i != precondMap.end(); ++i )
00167         {
00168             assert( statemapping.find( i->first ) != statemapping.end() );
00169             StateInterface* tgtState = statemapping[i->first];
00170             ConditionInterface* condition = i->second.first->copy( replacements );
00171             int line = i->second.second;
00172             ret->preconditionSet( tgtState, condition, line );
00173         }
00174 
00175         // init the StateMachine itself :
00176         ret->setFinalState( statemapping[ getFinalState() ]);
00177         ret->setInitialState( statemapping[ getInitialState() ]);
00178 
00179         return ret;
00180     }
00181 
00182     ParsedStateMachine::~ParsedStateMachine() {
00183         this->smStatus = Status::unloaded;
00184         this->handleUnload();
00185 
00186         // we own our states...
00187         for ( TransitionMap::iterator i = stateMap.begin();
00188               i != stateMap.end(); ++i )
00189             delete i->first;
00190         // we own our conditions...
00191         for ( TransitionMap::iterator i = stateMap.begin();
00192               i != stateMap.end(); ++i )
00193             for ( TransList::iterator i2 = i->second.begin(); i2 != i->second.end(); ++i2 )
00194                 delete get<0>( *i2 );  // delete the condition.
00195 
00196         // we own our event guards...
00197         for ( EventMap::iterator i = eventMap.begin();
00198               i != eventMap.end(); ++i )
00199             for ( EventList::iterator i2 = i->second.begin(); i2 != i->second.end(); ++i2 )
00200                 delete get<4>( *i2 );  // delete the condition.
00201     }
00202 
00203     ParsedStateMachine::ParsedStateMachine()
00204         : StateMachine( StateMachinePtr() ), object(0) // no parent, no task
00205     {
00206         _text.reset( new string("No Text Set.") );
00207     }
00208 
00209     void ParsedStateMachine::handleUnload()
00210     {
00211         // just kill off the interface.
00212         if ( object == 0)
00213             return;
00214         if ( object->getParent() ) {
00215             assert( object == object->getParent()->getObject( object->getName() ) );
00216             object->getParent()->removeObject( object->getName() );
00217         } else {
00218             // no parent, delete it ourselves.
00219             delete object;
00220         }
00221         object = 0;
00222     }
00223 
00224     void ParsedStateMachine::addParameter( const std::string& name, AttributeBase* var )
00225     {
00226         assert( parametervalues.find( name ) == parametervalues.end() );
00227         parametervalues[name] = var;
00228         // every parameter is also a readonly var...
00229         // visiblereadonlyvalues[name] = var->toDataSource();
00230     }
00231 
00232     AttributeBase* ParsedStateMachine::getParameter( const std::string& name ) const
00233     {
00234         if( parametervalues.find( name ) == parametervalues.end() )
00235             return 0;
00236         return parametervalues.find(name)->second;
00237     }
00238 
00239     ParsedStateMachine::VisibleWritableValuesMap ParsedStateMachine::getParameters() const
00240     {
00241         return parametervalues;
00242     }
00243 
00244     std::vector<std::string> ParsedStateMachine::getParameterNames() const
00245     {
00246         return keys( parametervalues );
00247     }
00248 
00249     void ParsedStateMachine::setName( const std::string& name, bool recursive )
00250     {
00251         // XXX BIG NOTE :
00252         // this function should me named 'instantiate' or so because it does more than
00253         // settting the name, it also recursively arranges names of children and
00254         // sets the parent-child TC connections. Reed the 'recursive' flag as 'instantiate'.
00255         // it is used only recursively for instantiating root contexts.
00256         //cerr << "Setting name "<< _name << " to " << name<<" rec: "<<recursive<<endl;
00257         // set the StateMachine name
00258         this->_name = name;
00259         // set the datasource's name
00260         //nameds->set( name );
00261 
00262         if ( recursive == false )
00263             return;
00264         //this->getTaskObject()->addPeer( this->getTaskObject()->getPeer("states")->getPeer("task") );
00265         for ( ChildList::const_iterator i = getChildren().begin(); i != getChildren().end(); ++i )
00266         {
00267             std::string subname = name + "." + (*i)->getName();
00268             ParsedStateMachine* psc = static_cast<ParsedStateMachine*>( i->get() );
00269             psc->setName( subname, true );
00270             // we own our child:
00271             psc->getTaskObject()->setParent( 0 );
00272             this->getTaskObject()->addObject( psc->getTaskObject() );
00273         }
00274     }
00275 
00276     std::string ParsedStateMachine::getText() const
00277     {
00278         return *_text;
00279     }
00280 
00281     void ParsedStateMachine::setText( std::string text)
00282     {
00283         *_text = text;
00284     }
00285 
00286     StateMachineTask* ParsedStateMachine::getTaskObject() const {
00287         return object;
00288     }
00289     void ParsedStateMachine::setTaskObject(StateMachineTask* tc) {
00290         object = tc;
00291         if (tc) {
00292             this->eproc = tc->events()->getEventProcessor();
00293             assert(this->eproc);
00294         }
00295     }
00296 
00297     bool ParsedStateMachine::inState( const std::string& name ) {
00298         StateInterface* copy = this->currentState();
00299         if (copy == 0)
00300             return false;
00301         return copy->getName() == name;
00302     }
00303 
00304     void ParsedStateMachine::finish()
00305     {
00306     }
00307 
00308 }

Generated on Tue Mar 25 17:41:49 2008 for OrocosReal-TimeToolkit by  doxygen 1.5.3