diff -rNu Workflow-1.32.orig/MANIFEST Workflow-1.32/MANIFEST
--- Workflow-1.32.orig/MANIFEST 2009-01-27 02:07:31.000000000 +1100
+++ Workflow-1.32/MANIFEST 2009-01-28 18:50:30.000000000 +1100
@@ -92,6 +92,7 @@
t/context.t
t/exception.t
t/factory.t
+t/factory_callback_config.t
t/factory_subclass.t
t/FactorySubclass.pm
t/history.t
@@ -112,6 +113,7 @@
t/TestApp/Action/TicketCreate.pm
t/TestApp/Action/TicketCreateType.pm
t/TestApp/Action/TicketUpdate.pm
+t/TestApp/Condition/AlwaysTrue.pm
t/TestApp/Condition/HasUser.pm
t/TestApp/Condition/HasUserType.pm
t/TestApp/Ticket.pm
@@ -129,14 +131,17 @@
t/workflow.xml
t/workflow_action.perl
t/workflow_action.xml
+t/workflow_action_callback.xml
t/workflow_action_type.perl
t/workflow_action_type.xml
t/workflow_autorun.xml
t/workflow_cached_condition.xml
t/workflow_cached_condition_action.xml
t/workflow_cached_condition_condition.xml
+t/workflow_callback.xml
t/workflow_condition.perl
t/workflow_condition.xml
+t/workflow_condition_callback.xml
t/workflow_condition_type.perl
t/workflow_condition_type.xml
t/workflow_errorprone.perl
diff -rNu Workflow-1.32.orig/lib/Workflow/Factory.pm Workflow-1.32/lib/Workflow/Factory.pm
--- Workflow-1.32.orig/lib/Workflow/Factory.pm 2009-01-27 02:07:31.000000000 +1100
+++ Workflow-1.32/lib/Workflow/Factory.pm 2009-01-28 17:18:42.000000000 +1100
@@ -56,7 +56,7 @@
my $INITIAL_STATE = 'INITIAL';
-my @FIELDS = qw();
+my @FIELDS = qw(config_callback);
__PACKAGE__->mk_accessors(@FIELDS);
sub new {
@@ -405,8 +405,19 @@
$wf->add_observer($_) for ( @{$observers} );
}
+sub _initialize_workflow_config {
+ my $self = shift;
+ my $wf_type = shift;
+ $log ||= get_logger();
+ if ( ref($self->config_callback) eq 'CODE' ) {
+ my $args = &{ $self->config_callback }( $wf_type );
+ $self->add_config_from_file( %$args ) if $args && %$args;
+ }
+}
+
sub _get_workflow_config {
my ( $self, $wf_type ) = @_;
+ $self->_initialize_workflow_config( $wf_type ) unless $self->{_workflow_config}{ $wf_type };
return $self->{_workflow_config}{$wf_type};
}
@@ -1001,6 +1012,44 @@
L</instance> should be called or the imported 'FACTORY' should be utilized.
+=head1 DYNAMIC CONFIG LOADING
+
+If you have either a large set of config files or a set of very large
+config files then you may not want to incur the overhead of loading
+each and every one on startup if you cannot predict which set you will
+use in that instance of your application.
+
+This approach doesn't make much sense in a persistent environment such
+as mod_perl but it may lower startup costs if you have regularly
+scheduled scripts that may not need to touch all possible types of
+workflow.
+
+To do this you can specify a callback that the factory will use to
+retrieve batched hashes of config declarations. Whenever an unknown
+workflow name is encountered the factory will first try to load your
+config declarations then continue.
+
+The callback takes one argument which is the workflow type. It should
+return a reference to a hash of arguments in a form suitable for
+C<add_config_from_file>.
+
+For example:
+
+ use Workflow::Factory qw(FACTORY);
+ use My::Config::System;
+
+ sub init {
+ my $self = shift;
+
+ FACTORY->config_callback(
+ sub {
+ my $wf_type = shift;
+ my %ret = My::Config::System->get_files_for_wf( $wf_type ) || ();
+ return \%ret;
+ }
+ );
+ }
+
=head1 SUBCLASSING
=head2 Implementation and Usage
diff -rNu Workflow-1.32.orig/t/TestApp/Condition/AlwaysTrue.pm Workflow-1.32/t/TestApp/Condition/AlwaysTrue.pm
--- Workflow-1.32.orig/t/TestApp/Condition/AlwaysTrue.pm 1970-01-01 10:00:00.000000000 +1000
+++ Workflow-1.32/t/TestApp/Condition/AlwaysTrue.pm 2009-01-28 17:41:33.000000000 +1100
@@ -0,0 +1,19 @@
+package TestApp::Condition::AlwaysTrue;
+
+# $Id$
+
+use strict;
+use base qw( Workflow::Condition );
+use Log::Log4perl qw( get_logger );
+use Workflow::Exception qw( condition_error );
+
+$TestApp::Condition::AlwaysTrue::VERSION = '0.01';
+
+sub evaluate {
+ my ( $self, $wf ) = @_;
+ my $log = get_logger();
+ $log->debug( "Trying to execute condition ", ref( $self ) );
+ $log->debug( 'Condition met ok' );
+}
+
+1;
diff -rNu Workflow-1.32.orig/t/factory_callback_config.t Workflow-1.32/t/factory_callback_config.t
--- Workflow-1.32.orig/t/factory_callback_config.t 1970-01-01 10:00:00.000000000 +1000
+++ Workflow-1.32/t/factory_callback_config.t 2009-01-29 09:39:39.000000000 +1100
@@ -0,0 +1,39 @@
+# -*-perl-*-
+
+# $Id$
+
+use strict;
+use lib 't';
+use TestUtil;
+use Test::More tests => 7;
+use Test::Exception;
+
+require_ok( 'Workflow::Factory' );
+
+my $factory = Workflow::Factory->instance();
+my $wf;
+
+lives_ok { TestUtil->init_mock_persister }
+ 'Loading test persister succeeds';
+
+dies_ok { $wf = $factory->create_workflow( 'CallbackTest' ) }
+ 'Attempt to create new workflow without loading its config first dies';
+
+can_ok( $factory, 'config_callback' );
+
+lives_ok { $factory->config_callback( sub {
+ my $type = shift;
+ if ($type eq 'CallbackTest') {
+ return { workflow => 'workflow_callback.xml',
+ action => 'workflow_action_callback.xml',
+ condition => 'workflow_condition_callback.xml' };
+ }
+ return {};
+ } ) }
+ 'Setting callback function succeeds';
+
+dies_ok { $wf = $factory->create_workflow( 'CallbackTestBogus' ) }
+ 'Attempt to create unknown workflow still dies';
+
+lives_ok { $wf = $factory->create_workflow( 'CallbackTest' ) }
+ 'Attempt to create known workflow via callback succeeds';
diff -rNu Workflow-1.32.orig/t/workflow_action_callback.xml Workflow-1.32/t/workflow_action_callback.xml
--- Workflow-1.32.orig/t/workflow_action_callback.xml 1970-01-01 10:00:00.000000000 +1000
+++ Workflow-1.32/t/workflow_action_callback.xml 2009-01-28 18:18:45.000000000 +1100
@@ -0,0 +1,8 @@
+<actions>
+ <type>CallbackTest</type>
+ <description>Actions for the CallbackTest workflow only</description>
+
+ <action name="CALLBACK_CLOSE" class="Workflow::Action::Null">
+ <description>Dummy close a callback test workflow</description>
+ </action>
+</actions>
\ No newline at end of file
diff -rNu Workflow-1.32.orig/t/workflow_callback.xml Workflow-1.32/t/workflow_callback.xml
--- Workflow-1.32.orig/t/workflow_callback.xml 1970-01-01 10:00:00.000000000 +1000
+++ Workflow-1.32/t/workflow_callback.xml 2009-01-29 09:40:17.000000000 +1100
@@ -0,0 +1,17 @@
+<workflow>
+ <type>CallbackTest</type>
+ <description>This is a sample workflow used to test loading config on demand</description>
+ <persister>TestPersister</persister>
+ <state name="INITIAL">
+ <description>This is the state the workflow enters when
+ instantiated. It's like a 'state zero' but since we're
+ using names rather than IDs we cannot assume</description>
+ <action name="CALLBACK_CLOSE" resulting_state="Callback_Closed">
+ <condition name="CallbackAlwaysTrue"/>
+ </action>
+ </state>
+
+ <state name="Callback_Closed">
+ <description>Placeholder closed state</description>
+ </state>
+</workflow>
diff -rNu Workflow-1.32.orig/t/workflow_condition_callback.xml Workflow-1.32/t/workflow_condition_callback.xml
--- Workflow-1.32.orig/t/workflow_condition_callback.xml 1970-01-01 10:00:00.000000000 +1000
+++ Workflow-1.32/t/workflow_condition_callback.xml 2009-01-28 17:38:24.000000000 +1100
@@ -0,0 +1,4 @@
+<conditions>
+ <type>CallbackTest</type>
+ <condition name="CallbackAlwaysTrue" class="TestApp::Condition::AlwaysTrue"/>
+</conditions>