ResultFactory.pm revision 1.5
1package TAP::Parser::ResultFactory; 2 3use strict; 4use warnings; 5 6use TAP::Parser::Result::Bailout (); 7use TAP::Parser::Result::Comment (); 8use TAP::Parser::Result::Plan (); 9use TAP::Parser::Result::Pragma (); 10use TAP::Parser::Result::Test (); 11use TAP::Parser::Result::Unknown (); 12use TAP::Parser::Result::Version (); 13use TAP::Parser::Result::YAML (); 14 15use base 'TAP::Object'; 16 17############################################################################## 18 19=head1 NAME 20 21TAP::Parser::ResultFactory - Factory for creating TAP::Parser output objects 22 23=head1 SYNOPSIS 24 25 use TAP::Parser::ResultFactory; 26 my $token = {...}; 27 my $factory = TAP::Parser::ResultFactory->new; 28 my $result = $factory->make_result( $token ); 29 30=head1 VERSION 31 32Version 3.44 33 34=cut 35 36our $VERSION = '3.44'; 37 38=head2 DESCRIPTION 39 40This is a simple factory class which returns a L<TAP::Parser::Result> subclass 41representing the current bit of test data from TAP (usually a single line). 42It is used primarily by L<TAP::Parser::Grammar>. Unless you're subclassing, 43you probably won't need to use this module directly. 44 45=head2 METHODS 46 47=head2 Class Methods 48 49=head3 C<new> 50 51Creates a new factory class. 52I<Note:> You currently don't need to instantiate a factory in order to use it. 53 54=head3 C<make_result> 55 56Returns an instance the appropriate class for the test token passed in. 57 58 my $result = TAP::Parser::ResultFactory->make_result($token); 59 60Can also be called as an instance method. 61 62=cut 63 64sub make_result { 65 my ( $proto, $token ) = @_; 66 my $type = $token->{type}; 67 return $proto->class_for($type)->new($token); 68} 69 70=head3 C<class_for> 71 72Takes one argument: C<$type>. Returns the class for this $type, or C<croak>s 73with an error. 74 75=head3 C<register_type> 76 77Takes two arguments: C<$type>, C<$class> 78 79This lets you override an existing type with your own custom type, or register 80a completely new type, eg: 81 82 # create a custom result type: 83 package MyResult; 84 use strict; 85 use base 'TAP::Parser::Result'; 86 87 # register with the factory: 88 TAP::Parser::ResultFactory->register_type( 'my_type' => __PACKAGE__ ); 89 90 # use it: 91 my $r = TAP::Parser::ResultFactory->( { type => 'my_type' } ); 92 93Your custom type should then be picked up automatically by the L<TAP::Parser>. 94 95=cut 96 97our %CLASS_FOR = ( 98 plan => 'TAP::Parser::Result::Plan', 99 pragma => 'TAP::Parser::Result::Pragma', 100 test => 'TAP::Parser::Result::Test', 101 comment => 'TAP::Parser::Result::Comment', 102 bailout => 'TAP::Parser::Result::Bailout', 103 version => 'TAP::Parser::Result::Version', 104 unknown => 'TAP::Parser::Result::Unknown', 105 yaml => 'TAP::Parser::Result::YAML', 106); 107 108sub class_for { 109 my ( $class, $type ) = @_; 110 111 # return target class: 112 return $CLASS_FOR{$type} if exists $CLASS_FOR{$type}; 113 114 # or complain: 115 require Carp; 116 Carp::croak("Could not determine class for result type '$type'"); 117} 118 119sub register_type { 120 my ( $class, $type, $rclass ) = @_; 121 122 # register it blindly, assume they know what they're doing 123 $CLASS_FOR{$type} = $rclass; 124 return $class; 125} 126 1271; 128 129=head1 SUBCLASSING 130 131Please see L<TAP::Parser/SUBCLASSING> for a subclassing overview. 132 133There are a few things to bear in mind when creating your own 134C<ResultFactory>: 135 136=over 4 137 138=item 1 139 140The factory itself is never instantiated (this I<may> change in the future). 141This means that C<_initialize> is never called. 142 143=item 2 144 145C<TAP::Parser::Result-E<gt>new> is never called, $tokens are reblessed. 146This I<will> change in a future version! 147 148=item 3 149 150L<TAP::Parser::Result> subclasses will register themselves with 151L<TAP::Parser::ResultFactory> directly: 152 153 package MyFooResult; 154 TAP::Parser::ResultFactory->register_type( foo => __PACKAGE__ ); 155 156Of course, it's up to you to decide whether or not to ignore them. 157 158=back 159 160=head2 Example 161 162 package MyResultFactory; 163 164 use strict; 165 166 use MyResult; 167 168 use base 'TAP::Parser::ResultFactory'; 169 170 # force all results to be 'MyResult' 171 sub class_for { 172 return 'MyResult'; 173 } 174 175 1; 176 177=head1 SEE ALSO 178 179L<TAP::Parser>, 180L<TAP::Parser::Result>, 181L<TAP::Parser::Grammar> 182 183=cut 184