# File: Stem/Cell/Sequence.pm
# This file is part of Stem.
# Copyright (C) 1999, 2000, 2001 Stem Systems, Inc.
# Stem is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# Stem 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with Stem; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# For a license to use the Stem under conditions other than those
# described here, to purchase support for this software, or to purchase a
# commercial warranty contract, please contact Stem Systems at:
# Stem Systems, Inc. 781-643-7504
# 79 Everett St. info@stemsystems.com
# Arlington, MA 02474
# USA
package Stem::Cell ;
use strict ;
sub cell_set_sequence {
my( $self, @sequence ) = @_ ;
my $cell_info = $self->_get_cell_info() ;
#print "@sequence\n" ;
$cell_info->{'sequence'} = [ @sequence ] ;
$cell_info->{'sequence_left'} = [ @sequence ] ;
return ;
}
sub cell_reset_sequence {
my( $self ) = @_ ;
my $cell_info = $self->_get_cell_info() ;
$cell_info->{'sequence_left'} = [ @{$cell_info->{'sequence'}} ] ;
return ;
}
sub cell_replace_next_sequence {
my( $self, $method ) = @_ ;
my $cell_info = $self->_get_cell_info() ;
$cell_info->{'sequence_left'}[0] = $method;
return ;
}
#
# This method lets you basically set up loops. For example, method X
# could insert itself as the next next method in the sequence. Then,
# when it is called again it can decide whether or not to insert
# itself again.
#
# A more complex example might see method X might say "now execute Y,
# Z, M, and X", which allows you to create loops. Then method Z might
# say "now execute Q and Z".
#
# Obviously, most loops will also need a break condition where method
# X decides _not_ to insert itself into the sequence.
#
sub cell_insert_next_sequence {
my( $self, @sequence ) = @_ ;
my $cell_info = $self->_get_cell_info() ;
unshift @{ $cell_info->{'sequence_left'} }, @sequence;
return ;
}
sub cell_skip_next_sequence {
my( $self, $count ) = @_ ;
$count ||= 1 ;
my $cell_info = $self->_get_cell_info() ;
shift @{ $cell_info->{'sequence_left'} } for 1..$count;
return ;
}
sub cell_skip_until_method {
my( $self, $method ) = @_ ;
my $cell_info = $self->_get_cell_info() ;
my $seq_left = $cell_info->{'sequence_left'} ;
while( @{$seq_left} ) {
return if $seq_left->[0] eq $method ;
shift @{$seq_left} ;
}
die "skip sequence method $method is not found" ;
}
sub cell_next_sequence_in {
my( $self, $msg ) = @_ ;
#print $msg->dump( "NEXT IN" ) if $msg ;
my $cell_info = $self->_get_cell_info() ;
$cell_info->cell_next_sequence( $msg ) ;
}
sub cell_next_sequence {
my( $self, $in_msg ) = @_ ;
#print caller(), "\n" ;
#print $in_msg->dump('SEQ IN') if $in_msg ;
my $cell_info = $self->_get_cell_info() ;
my $owner_obj = $cell_info->{'owner_obj'} ;
while( my $next_sequence = shift @{$cell_info->{'sequence_left'}} ) {
#print "LEFT @{$cell_info->{'sequence_left'}}\n" ;
die "cannot call sequence method $next_sequence"
unless $owner_obj->can( $next_sequence ) ;
#print "SEQ: $next_sequence\n" ;
my $seq_val = $owner_obj->$next_sequence( $in_msg ) ;
# don't pass in the message more than once.
$in_msg = undef ;
next unless $seq_val ;
if ( ref $seq_val eq 'Stem::Msg' ) {
#print caller() ;
#print $seq_val->dump( 'SEQ: MSG' ) ;
$seq_val->reply_type( 'cell_next_sequence' ) ;
$seq_val->dispatch() ;
return ;
}
if ( ref $seq_val eq 'HASH' ) {
my $delay = $seq_val->{'delay'} ;
if ( defined( $delay ) ) {
$cell_info->cell_sequence_delay( $delay ) ;
return ;
}
}
}
if ( my $seq_done_method = $cell_info->{'sequence_done_method'} ) {
$owner_obj->$seq_done_method() ;
return ;
}
#warn "FELL off end of sequence" ;
return ;
}
sub cell_sequence_delay {
my( $self, $delay ) = @_ ;
my $cell_info = $self->_get_cell_info() ;
#print "SEQ DELAY $delay\n" ;
$cell_info->{'timer'} = Stem::Event::Timer->new(
'object' => $cell_info,
'method' => 'cell_next_sequence',
'delay' => $delay,
'hard' => 1,
'single' => 1,
) ;
}
1 ;