From: Chris W. <la...@us...> - 2005-02-13 20:37:43
|
Update of /cvsroot/openinteract/OpenInteract2/lib/OpenInteract2 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9810/OpenInteract2 Added Files: ActionResolver.pm Log Message: add parent class (ActionResolver) that organizes children and provides a facade for a chain of responsibility to that resolves a URL to an OI2 action; previously this was spread over OI2::Request and OI2::Controller; now it's encapsulated in smaller, more focused classes --- NEW FILE: ActionResolver.pm --- package OpenInteract2::ActionResolver; # $Id: ActionResolver.pm,v 1.1 2005/02/13 20:37:35 lachoy Exp $ use strict; use base qw( Class::Factory ); use Log::Log4perl qw( get_logger ); use OpenInteract2::Constants qw( LOG_ACTION ); use OpenInteract2::Exception qw( oi_error ); use OpenInteract2::URL; use OpenInteract2::Util; my ( $log ); $OpenInteract2::ActionResolver::VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/); sub resolver_sort { return $a->get_order <=> $b->get_order; } sub get_all_resolvers { my ( $class ) = @_; my @all_resolver_types = $class->get_registered_types(); my @resolvers = (); foreach my $type ( @all_resolver_types ) { push @resolvers, $class->new( $type ); } return sort resolver_sort @resolvers; } sub get_action { my ( $class, $request, @other ) = @_; $log ||= get_logger( LOG_ACTION ); my ( $url ); my @resolvers = (); if ( scalar @other ) { unless ( ref $other[0] ) { $url = OpenInteract2::URL->parse_absolute_to_relative( shift @other ); } @resolvers = @other; } unless ( scalar @resolvers ) { @resolvers = $class->get_all_resolvers; } $url ||= $request->url_relative; $log->info( "Sending URL '$url' to ", scalar( @resolvers ), " ", "action resolvers" ); my ( $action ); foreach my $r ( @resolvers ) { $action = eval { $r->resolve( $request, $url ) }; if ( $@ ) { $log->warn( "Resolver ", ref( $r ), " threw an ", "exception ($@); continuing with others..." ); } last if ( $action ); } return $action; } ######################################## # SUBCLASSES sub resolve { _must_implement( 'resolve', @_ ) } sub get_order { return 5 } sub _must_implement { my ( $method, $item ) = @_; my $class = ref( $item ) || $item; oi_error "Class '$class' must implement method '$method'"; } OpenInteract2::Util->find_factory_subclasses( 'OpenInteract2::ActionResolver', @INC ); 1; __END__ =head1 NAME OpenInteract2::ActionResolver - Small classes and chain of responsibility to resolve URLs to action objects =head1 SYNOPSIS # Get all the available resolver objects my @resolvers = OpenInteract2::ActionResolver->get_all_resolvers(); # Send OI2::Request object from which we get the URL using the # default resolvers... my $action = OpenInteract2::ActionResolver->get_action( $request ); # ...or specify the URL and resolvers yourself my $action = OpenInteract2::ActionResolver->get_action( $request, $url, @resolvers ); =head1 DESCRIPTION An action resolver takes a URL and tries to create an L<OpenInteract2::Action> from it. If the resolver cannot do so it does nothing and the next one is called. Resolvers are found at runtime as long as they're under the 'OpenInteract2::ActionResolver' namespace. You can also add them manually using normal L<Class::Factory> directives: OpenInteract2::ActionResolver->register_factory_class( myresolver => 'MyApplication::Resolver::FooResolver' ); =head1 CLASS METHODS C<get_all_resolvers()> Returns a list of resolver objects -- order is important! C<get_action( $request, [ $url ], [ @resolvers ] )> Match up C<$url> to the corresponding action. If not given we ask C<$request> for its C<url_relative()> property, and if C<@resolvers> aren't given we use the result from our C<get_all_resolvers()> class method. Each of the L<OpenInteract2::ActionResolver> objects in C<@resolvers> will get called and asked if it can resolve C<$url> This will either return an L<OpenInteract2::Action> object or throw an exception. C<new( $type )> Creates a new resolver -- no parameters are passed in besides the C<$type> that each resolver uses to register itself. =head1 OBJECT METHODS B<get_order()> - subclass may implement Return a number between 1 and 10 indicating when the resolver should be run. If you do not implement this the default is '5', which will probably be fine for most implementations. B<resolve( $request, $url )> - subclass must implement Tries to find data in C<$url> to create an action. The C<$url> will B<not> contain any deployment context information. (Note that C<$url> may have come from C<$request> or may have been specified by the original caller, so don't go peeking around in C<$request> for it unless you know what you're doing.) If that particular resolver does not know what to do with the URL it should return nothing to indicate that the next resolver down the line should get executed. The object may also create side-effects along the way. For instance, one of the built-in resolvers finds a parameter 'oi_language' from C<$request> and if it exists assigns that language for the request. (Yes, this technically isn't resolving an action, but there's no real use to create B<another> set of classes that perform such a similar action.) =head1 SEE ALSO L<OpenInteract2::Controller> L<OpenInteract2::Action> =head1 COPYRIGHT Copyright (c) 2005 Chris Winters. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHORS Chris Winters E<lt>ch...@cw...E<gt> |