The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

SPOPS::ClassFactory - Create SPOPS classes from configuration and code

SYNOPSIS

 # Using SPOPS::Initialize (strongly recommended)
 
 my $config = { ... };
 SPOPS::Initialize->process({ config => $config });
 
 # Using SPOPS::ClassFactory
 
 my $config = {};
 my $classes_created = SPOPS::ClassFactory->create( $config );
 foreach my $class ( @{ $classes_created } ) {
     $class->class_initialize();
 }

DESCRIPTION

This class creates SPOPS classes. It replaces SPOPS::Configure -- if you try to use SPOPS::Configure you will (for the moment) get a warning about using a deprecated interface and call this module, but that will not last forever.

See SPOPS::Manual::CodeGeneration for a discussion of what this module does and how you can customize it.

METHODS

create( \%multiple_config, \%params )

Before you read on, are you sure you need to learn more about this process? If you are just using SPOPS (as opposed to extending it), you almost certainly want to look at SPOPS::Initialize instead since it hides all these machinations from you.

So, we can now assume that you want to learn about how this class works. This is the main interface into the class factory, and generally the only one you will probably ever need. Other methods in the class factory rely on configuration information in the object or on particular methods ('behavior generators') in the object or the parents of the object to provide the actions for the class factory to process.

Return value is an arrayref of classes created;

The first parameter is a series of SPOPS configurations, in the format:

 { alias => { ... },
   alias => { ... },
   alias => { ... } }

The second parameter is a hashref of options. Currently there is only one option supported, but the future could bring more options. Options right now:

  • alias_list (\@) (optional)

    List of aliases to process from \%multiple_config. If not given we simply read the keys of \%multiple_config, screening out those that begin with '_'.

    Use this if you only want to process a limited number of the SPOPS class definitions available in \%multiple_config.

Individual Configuration Methods

find_behavior( $class )

Find all the factory method-generators in all members of the inheritance tree for an SPOPS class, then run each of the generators and keep track of the slots each generator uses, a.k.a. the behavior map.

Return value is the behavior map, a hashref with keys as class names and values as arrayrefs of slot names. For instance:

 my $b_map = SPOPS::ClassFactory->find_behavior( 'My::SPOPS' );
 print "Behaviors retrieved for My::SPOPS\n";
 foreach my $class_name ( keys %{ $b_map } ) {
     print "  -- Retrieved from ($class_name): ",
           join( ', ' @{ $b_map->{ $class_name } } ), "\n";
 }

exec_behavior( $slot_name, $class )

Execute behavior rules in slot $slot_name collected by find_behavior() for $class.

Executing the behaviors in a slot succeeds if there are no behaviors to execute or if all the behaviors execute without returning an ERROR.

If a behavior returns an ERROR, the entire process is stopped and a SPOPS::Exception object is thrown with the message returned from the behavior.

If a behavior returns a RESTART, we re-find all behaviors for the class and if they do not match up with what was found earlier, run the behaviors that were not previously run before.

For instance, if a behavior changes the @ISA of a class (by modifying the {isa} configuration key), we need to check that class to see if it has any additional behaviors for our class. In theory, you could get into some hairy situations with this recursion -- e.g., two behaviors keep adding each other -- but practically it will rarely occur. (At least we hope so.)

Return value: true if success, throws SPOPS::Exception on failure.

create_stub( \%config )

Creates the class specified by \%config, sets its @ISA to what is set in \%config and ensures that all members of the @ISA are required.

Return value: same as any behavior (OK or ERROR/NOTIFY plus message).

require_config_classes( \%config )

Runs a 'require' on all members of the 'isa' and 'rules_from' keys in \%config.

Return value: same as a behavior (OK or ERROR/NOTIFY plus message).

install_configuration( $class, \%config )

Installs the configuration \%config to the class $class. This is a simple copy and we do not do any transformation of the data.

Return value: same as a behavior (OK or ERROR/NOTIFY plus message).

Multiple Configuration Methods

These methods are basically wrappers around the "Individual Configuration Methods" below, calling them once for each class to be configured.

create_all_stubs( \%multiple_config, \%params )

Creates all the necessary classes and installs the available configuration to each class.

Calls create_stub() and install_configuration().

find_all_behavior( \%multiple_config, \%params )

Retrieves behavior routines from all necessary classes.

Calls find_behavior().

exec_all_behavior( \%multiple_config, \%params )

Executes behavior routines in all necessary classes.

Calls exec_behavior()

clean_all_behavior( \%multiple_config, \%params )

Removes behavior routines and tracking information from the configuration of all necessary classes.

Calls: nothing.

Utility Methods

get_alias_list( \%multiple_config, \%params )

Looks at the 'alias_list' key in \%params for an arrayref of aliases; if it does not exist, pulls out the keys in \%multiple_config that do not begin with '_'.

Returns: arrayref of alias names.

find_parent_methods( $class, \@added_classes, @method_list )

Walks through the inheritance tree for $class as well as each of the classes specified in \@added_classes and finds all instances of any member of @method_list. The first match wins, and only one match will be returned per class.

Returns: arrayref of two-element arrayrefs describing all the places that $method_name can be executed in the inheritance tree; the first item is the class name, the second a code reference.

Example:

 my $parent_info = SPOPS::ClassFactory->find_parent_methods(
                            'My::Class', [], 'method_factory', 'method_generate' );
 foreach my $method_info ( @{ $parent_info } ) {
     print "Class $method_info->[0] found sub which has the result: ",
           $method_info->[1]->(), "\n";
 }

sync_isa( $class )

Synchronize the @ISA in $class with the {isa} key in its configuration. Also requires all classes in the newly synchronized @ISA.

Returns true if there are no problems, throws a SPOPS::Exception object otherwise. (The only reason it would fail is if a recently added class cannot be required.)

compare_behavior_map( \%behavior_map, \%behavior_map )

Returns true if the two are equivalent, false if not.

BUGS

None known (beyond being somewhat confusing).

TO DO

Nothing known.

SEE ALSO

SPOPS::Manual::CodeGeneration

SPOPS

COPYRIGHT

Copyright (c) 2001-2004 intes.net, inc.. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHORS

Chris Winters <chris@cwinters.com>