Hormiga 1.0

/var/www/hormigaproject.com.ar/files/src/step/step.cpp

Go to the documentation of this file.
00001 
00002 /*
00003 # Hormiga - Software de cálculo programable.
00004 #
00005 # Copyright (C) 2008, 2009 Leonardo Román, Hugo J. Curti, Norma  Ercoli,
00006 # Universidad Nacional del Centro de la Provincia de Buenos Aires
00007 # (UNCPBA)
00008 #
00009 # Este programa es parte de Hormiga.
00010 #
00011 # Hormiga es software libre. Puede redistribuirlo y/o modificarlo
00012 # bajo los términos de la Licencia Pública General de GNU según es
00013 # publicada por la Free Software Foundation, versión 2. Vea el archivo
00014 # COPIA (español, no oficial) o COPYING (inglés, oficial) en directorio
00015 # raíz.
00016 #
00017 # Hormiga se distribuye con la esperanza de que sea útil, pero SIN
00018 # NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL implícita o sin
00019 # garantizar la CONVENIENCIA PARA UN PROPÓSITO PARTICULAR. Véase la
00020 # Licencia Pública General de GNU para más detalles.
00021 #
00022 # Debería haber recibido una copia de la Licencia Pública General junto
00023 # con Hormiga. Si no ha sido así, escriba a la Free Software
00024 # Foundation, Inc., en 675 Mass Ave, Cambridge, MA 02139, EEUU.
00025 # Añada también información sobre cómo contactar con usted mediante
00026 # correo electrónico y postal.
00027 #
00028 # This file is part of Hormiga.
00029 #
00030 # Hormiga is free software; you can redistribute it and/or modify
00031 # it under the terms of the GNU General Public License version 2
00032 # as published by the Free Software Foundation; see the file COPYING
00033 # in the top directory for details.
00034 #
00035 # Hormiga is distributed in the hope that it will be useful,
00036 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00037 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00038 # GNU General Public License for more details.
00039 #
00040 # You should have received a copy of the GNU General Public License
00041 # along with Hormiga; if not, write to the Free Software
00042 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
00043 # USA
00044 */
00045 
00046 #include "step.h"
00047 #include "stdio.h"
00048 #include <QMetaType>
00049 Step::Step( T_STRING name )
00050 {
00051     this->name = name ;
00052     this->execBlock = NULL ;
00053     this->stepsNeeded = NULL ;
00054     this->captures = NULL ;
00055     this->reports = NULL ;
00056     this->condition = NULL ;
00057     unsatisfiedDependencesCount = 0 ;
00058     this->currentState = Step::Satisfied ;
00059     this->alreadyExecuted = false ;
00060 
00061     if ( QMetaType::type("Step") == 0 )
00062     {   /* We need to register our types used in signals */
00063         qRegisterMetaType<Step*>("Step") ;
00064         qRegisterMetaType<Step::state>("Step::state") ;
00065     }
00066 }
00067 
00068 Step::~Step()
00069 {
00070     if ( this->stepsNeeded != NULL ) delete this->stepsNeeded ;
00071     if ( this->captures != NULL ) delete this->captures ;
00072     if ( this->reports != NULL ) delete this->reports ;
00073     if ( this->execBlock != NULL ) delete this->execBlock ;
00074     if ( this->condition != NULL ) delete this->condition ;
00075 }
00076 
00077 
00078 T_STRING Step::toString () const
00079 {
00080     return ( this->name ) ;
00081 }
00082 
00083 T_STRING Step::getName ()
00084 {
00085     return ( this->name ) ;
00086 }
00087 
00088 void Step::run ()
00089 {
00090     this->exec( true ) ;
00091 }
00092 
00093 bool Step::exec ( bool interactive )
00094 {
00095     if ( this->currentState == Step::NotSatisfied )
00096         return ( false ) ;
00097     this->changeState( Step::Executing ) ;
00098     this->alreadyExecuted = true ;
00099     if ( this->captures != NULL && interactive )
00100     {
00101         /* We will wait here for user input (if any GUI is connected for) */
00102         emit needInput ( this , this->captures ) ;
00103         /* If the GUI is not "bloking" on connected slot then will need to sleep
00104            the Step thread
00105            */
00106     }
00107 
00108     execSleep.lock() ;
00109     bool result = this->execBlock->exec() ;
00110     execSleep.unlock() ;
00111 
00112     if ( this->reports != NULL && interactive )
00113         emit reportOutput( this, this->reports ) ;
00114 
00115     /* Are conditions OK ? */
00116     if ( this->condition != NULL && ! this->condition->eval() )
00117     {
00118         result = FALSE ;
00119         this->showMessage( 2, this->condition->getText() ) ;
00120     }
00121     /* Wait for GUI to show the reports, if is any */
00122     execSleep.lock() ;
00123     // Se cumplen las condiciones ?
00124     if ( result )
00125     {
00126         this->changeState( Step::Accepted ) ;
00127     } else {
00128         this->changeState( Step::Satisfied ) ;
00129     }
00130     execSleep.unlock() ;
00131     return ( true ) ;
00132 }
00133 
00134 void Step::setStepNeeds ( T_STEP_LIST *stepsNeeded )
00135 {
00136     if ( stepsNeeded == NULL )
00137         return ;
00138     this->stepsNeeded = stepsNeeded ;
00139     for ( int i = 0 ; i < stepsNeeded->count() ; i++ )
00140     {
00141         QObject::connect ( stepsNeeded->at( i ) , SIGNAL (
00142                              stateChanged(Step*,Step::state,Step::state) ) ,
00143                            this , SLOT (
00144                              notifyStepState( Step*, Step::state,Step::state) )
00145                          ) ;
00146     }
00147 
00148     this->unsatisfiedDependencesCount = stepsNeeded->count() ;
00149     // By now... this is the unique option:
00150     this->changeState( Step::NotSatisfied ) ;
00151 }
00152 
00153 void Step::setExecutionBlock ( Statement *execBlock )
00154 {
00155     this->execBlock = execBlock ;
00156 }
00157 
00158 void Step::setCaptures ( T_CAPTURE_LIST *clist )
00159 {
00160     this->captures = clist ;
00161 }
00162 
00163 void Step::setReports ( T_REPORT_LIST *reports )
00164 {
00165     this->reports = reports ;
00166 }
00167 
00168 void Step::setStepCondition ( StepCondition *condition )
00169 {
00170     this->condition = condition ;
00171 }
00172 
00173 void Step::changeState ( Step::state newState )
00174 {
00175     if ( this->currentState != newState )
00176     {
00177         Step::state oldState = this->currentState ;
00178         this->currentState = newState ;
00179         emit stateChanged( this , newState , oldState ) ;
00180     }
00181 }
00182 
00183 /* Slots */
00184 void Step::notifyStepState( Step* peer , Step::state newState ,
00185                             Step::state oldState )
00186 {
00187     /* - de <cualquier_estado> a [aceptado] : counter--
00188      * - de [aceptado] a  <cualquier_estado> : counter ++
00189      * Deberiamos verificar que 'peer' sea uno de los de la lista de
00190      * dependencias ? Por ahora "confiaremos" en que si.
00191      */
00192     if ( ( newState == Step::Accepted ) || ( oldState == Step::Accepted ) )
00193         printf("Step %s notified. Step %s state changed from %d to %d\n",
00194            this->getName().toAscii().data(),
00195            peer->getName().toAscii().data(), oldState, newState );
00196     if ( newState == Step::Accepted )
00197     {
00198         this->unsatisfiedDependencesCount-- ;
00199         if ( this->unsatisfiedDependencesCount == 0 )
00200         {
00201             this->changeState( Step::Satisfied ) ;
00202             // We should re-run this step ? -> this->start() ;
00203             if ( this->alreadyExecuted )
00204                 this->exec( false ) ; // Re-run me serialized ;)
00205         }
00206     }
00207     else if ( oldState == Step::Accepted )
00208     {
00209         this->unsatisfiedDependencesCount++ ;
00210         this->changeState( Step::NotSatisfied ) ;
00211     }
00212 }
00213 
00214 
00215 StepConditionSingle::StepConditionSingle ( Operand *condition , T_STRING text )
00216 {
00217     this->condition = condition ;
00218     this->text = text ;
00219 }
00220 
00221 StepConditionSingle::~StepConditionSingle()
00222 {
00223     if ( this->condition != NULL ) delete this->condition ;
00224 }
00225 
00226 bool StepConditionSingle::eval()
00227 {
00228     if ( this->condition == NULL ) return TRUE ;
00229     return ( ( this->condition->getValue() != FALSE )? TRUE : FALSE ) ;
00230 }
00231 
00232 T_STRING StepConditionSingle::getText()
00233 {
00234     return this->text ;
00235 }
00236 
00237 
00238 
00239 StepConditionComposite::StepConditionComposite ( T_STEP_CONDITIONS_LIST* list )
00240 {
00241     this->list = list ;
00242     this->last = NULL ;
00243 }
00244 
00245 StepConditionComposite::~StepConditionComposite ()
00246 {
00247     for ( int i = 0 ; i < list->count() ; i++ )
00248         delete list->takeFirst() ;
00249     delete this->list ;
00250 }
00251 
00252 bool StepConditionComposite::eval()
00253 {
00254     for ( int i = 0 ; i < list->count() ; i++ )
00255     {
00256         this->last = this->list->at( i ) ;
00257         if ( ! this->last->eval() )
00258             return FALSE ;
00259     }
00260     return TRUE ;
00261 }
00262 
00263 T_STRING StepConditionComposite::getText()
00264 {
00265     if ( this->last != NULL )
00266         return this->last->getText() ;
00267     return "" ;
00268 }