#!/usr/bin/perl
package Class::Workflow::Instance;
use Moose::Role;
with 'MooseX::Clone';
has prev => ( # the instance this instance was derived from
does => "Class::Workflow::Instance",
is => "ro",
required => 0,
);
has transition => ( # the transition this instance is a result of
does => "Class::Workflow::Transition",
is => "ro",
required => 0,
);
has state => ( # the state the instance is currently in
does => "Class::Workflow::State",
is => "ro",
required => 1,
);
sub derive {
my ( $self, @fields ) = @_;
$self->clone( @fields, prev => $self );
}
sub _clone {
my ( $self, @args ) = @_;
$self->clone(@args);
}
# FIXME push this feature to MooseX::Clone by using special values ( \$MooseX::Clone::CLEAR or somesuch )
around clone => sub {
my ( $next, $self, %fields ) = @_;
my @clear = grep { not defined $fields{$_} } keys %fields;
delete @fields{@clear};
my $clone = $self->$next(%fields);
my $meta = Class::MOP::get_metaclass_by_name(ref $self);
foreach my $field ( @clear ) {
$meta->find_attribute_by_name($field)->clear_value($clone);
}
return $clone;
};
__PACKAGE__;
__END__
=pod
=head1 NAME
Class::Workflow::Instance - An instance in a workflow, with state and history.
=head1 SYNOPSIS
package MyInstance;
use Moose;
with qw(Class::Workflow::Instance);
my $instance = MyInstance->new( state => $initial_state );
my $new_instance = $transition->apply( $instance, @args );
# $instance is in $initial state, no transitions applied
# $new_instance may be in another state, $transition has been applied
# $new_instance->prev == $instance
=head1 DESCRIPTION
A workflow instance encapsulates the current state and workflow history on
behalf of some parent object that needs state management.
In L<Class::Workflow> these instances are functionally pure, that is they don't
change but instead derive their parent copies, and the reference from a given
item is to the most recently derived copy.
This eases auditing, reverting, and the writing of transitions.
=head1 FIELDS
=over 4
=item state
The state this instance is in. Required.
=item prev
The L<Class::Workflow::Instance> object this object was derived from. Optional.
=item transition
The transition that created this instance from C<prev>.
=back
=head1 METHODS
=over 4
=item derive %fields
Clones the object, setting C<prev> to the current object, and shadowing the
fields with new values from the key value pair list in the arguments.
=item clone %fields
The low level clone operation. If you need to override L<Moose> based cloning,
because your instance objects are e.g. L<DBIx::Class> objects (see the
F<examples> directory), then you would likely want to override this.
See L<MooseX::Clone> for more details.
=back
=cut