#!/usr/bin/perl package Class::Workflow::Instance; use Moose::Role; 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, %fields ) = @_; my %clear; foreach my $key ( %fields ) { if ( not defined $fields{$key} ) { delete $fields{$key}; $clear{$key} = 1; } } my $clone = $self->meta->clone_object( $self, %fields ); foreach my $attr ($self->meta->compute_all_applicable_attributes()) { if ( defined( my $init_arg = $attr->init_arg ) ) { if (exists $clear{$init_arg}) { $attr->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 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 object this object was derived from. Optional. =item transition The transition that created this instance from C. =back =head1 METHODS =over 4 =item derive %fields Clones the object, setting C 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 based cloning, because your instance objects are e.g. L objects (see the F directory), then you would likely want to override this. As a special case values of C in %fields will cause the clearer to be called, not the setter. =back =cut