Option to disable the charging of the setup fee while a package is suspended.
[freeside.git] / install / 5.005 / DBD-Pg-1.22-fixvercmp / t / lib / App / Info / Handler.pm
1 package App::Info::Handler;
2
3 # $Id: Handler.pm,v 1.1 2004-04-29 09:21:28 ivan Exp $
4
5 =head1 NAME
6
7 App::Info::Handler - App::Info event handler base class
8
9 =head1 SYNOPSIS
10
11   use App::Info::Category::FooApp;
12   use App::Info::Handler;
13
14   my $app = App::Info::Category::FooApp->new( on_info => ['default'] );
15
16 =head1 DESCRIPTION
17
18 This class defines the interface for subclasses that wish to handle events
19 triggered by App::Info concrete subclasses. The different types of events
20 triggered by App::Info can all be handled by App::Info::Handler (indeed, by
21 default they're all handled by a single App::Info::Handler object), and
22 App::Info::Handler subclasses may be designed to handle whatever events they
23 wish.
24
25 If you're interested in I<using> an App::Info event handler, this is probably
26 not the class you should look at, since all it does is define a simple handler
27 that does nothing with an event. Look to the L<App::Info::Handler
28 subclasses|"SEE ALSO"> included in this distribution to do more interesting
29 things with App::Info events.
30
31 If, on the other hand, you're interested in implementing your own event
32 handlers, read on!
33
34 =cut
35
36 use strict;
37 use vars qw($VERSION);
38 $VERSION = '0.22';
39
40 my %handlers;
41
42 =head1 INTERFACE
43
44 This section documents the public interface of App::Info::Handler.
45
46 =head2 Class Method
47
48 =head3 register_handler
49
50   App::Info::Handler->register_handler( $key => $code_ref );
51
52 This class method may be used by App::Info::Handler subclasses to register
53 themselves with App::Info::Handler. Multiple registrations are supported. The
54 idea is that a subclass can define different functionality by specifying
55 different strings that represent different modes of constructing an
56 App::Info::Handler subclass object. The keys are case-sensitve, and should be
57 unique across App::Info::Handler subclasses so that many subclasses can be
58 loaded and used separately. If the C<$key> is already registered,
59 C<register_handler()> will throw an exception. The values are code references
60 that, when executed, return the appropriate App::Info::Handler subclass
61 object.
62
63 =cut
64
65 sub register_handler {
66     my ($pkg, $key, $code) = @_;
67     Carp::croak("Handler '$key' already exists")
68       if $handlers{$key};
69     $handlers{$key} = $code;
70 }
71
72 # Register ourself.
73 __PACKAGE__->register_handler('default', sub { __PACKAGE__->new } );
74
75 ##############################################################################
76
77 =head2 Constructor
78
79 =head3 new
80
81   my $handler = App::Info::Handler->new;
82   $handler =  App::Info::Handler->new( key => $key);
83
84 Constructs an App::Info::Handler object and returns it. If the key parameter
85 is provided and has been registered by an App::Info::Handler subclass via the
86 C<register_handler()> class method, then the relevant code reference will be
87 executed and the resulting App::Info::Handler subclass object returned. This
88 approach provides a handy shortcut for having C<new()> behave as an abstract
89 factory method, returning an object of the subclass appropriate to the key
90 parameter.
91
92 =cut
93
94 sub new {
95     my ($pkg, %p) = @_;
96     my $class = ref $pkg || $pkg;
97     $p{key} ||= 'default';
98     if ($class eq __PACKAGE__ && $p{key} ne 'default') {
99         # We were called directly! Handle it.
100         Carp::croak("No such handler '$p{key}'") unless $handlers{$p{key}};
101         return $handlers{$p{key}}->();
102     } else {
103         # A subclass called us -- just instantiate and return.
104         return bless \%p, $class;
105     }
106 }
107
108 =head2 Instance Method
109
110 =head3 handler
111
112   $handler->handler($req);
113
114 App::Info::Handler defines a single instance method that must be defined by
115 its subclasses, C<handler()>. This is the method that will be executed by an
116 event triggered by an App::Info concrete subclass. It takes as its single
117 argument an App::Info::Request object, and returns a true value if it has
118 handled the event request. Returning a false value declines the request, and
119 App::Info will then move on to the next handler in the chain.
120
121 The C<handler()> method implemented in App::Info::Handler itself does nothing
122 more than return a true value. It thus acts as a very simple default event
123 handler. See the App::Info::Handler subclasses for more interesting handling
124 of events, or create your own!
125
126 =cut
127
128 sub handler { 1 }
129
130 1;
131 __END__
132
133 =head1 SUBCLASSING
134
135 I hatched the idea of the App::Info event model with its subclassable handlers
136 as a way of separating the aggregation of application metadata from writing a
137 user interface for handling certain conditions. I felt it a better idea to
138 allow people to create their own user interfaces, and instead to provide only
139 a few examples. The App::Info::Handler class defines the API interface for
140 handling these conditions, which App::Info refers to as "events".
141
142 There are various types of events defined by App::Info ("info", "error",
143 "unknown", and "confirm"), but the App::Info::Handler interface is designed to
144 be flexible enough to handle any and all of them. If you're interested in
145 creating your own App::Info event handler, this is the place to learn how.
146
147 =head2 The Interface
148
149 To create an App::Info event handler, all one need do is subclass
150 App::Info::Handler and then implement the C<new()> constructor and the
151 C<handler()> method. The C<new()> constructor can do anything you like, and
152 take any arguments you like. However, I do recommend that the first thing
153 you do in your implementation is to call the super constructor:
154
155   sub new {
156       my $pkg = shift;
157       my $self = $pkg->SUPER::new(@_);
158       # ... other stuff.
159       return $self;
160   }
161
162 Although the default C<new()> constructor currently doesn't do much, that may
163 change in the future, so this call will keep you covered. What it does do is
164 take the parameterized arguments and assign them to the App::Info::Handler
165 object. Thus if you've specified a "mode" argument, where clients can
166 construct objects of you class like this:
167
168   my $handler = FooHandler->new( mode => 'foo' );
169
170 You can access the mode parameter directly from the object, like so:
171
172   sub new {
173       my $pkg = shift;
174       my $self = $pkg->SUPER::new(@_);
175       if ($self->{mode} eq 'foo') {
176           # ...
177       }
178       return $self;
179   }
180
181 Just be sure not to use a parameter key name required by App::Info::Handler
182 itself. At the moment, the only parameter accepted by App::Info::Handler is
183 "key", so in general you'll be pretty safe.
184
185 Next, I recommend that you take advantage of the C<register_handler()> method
186 to create some shortcuts for creating handlers of your class. For example, say
187 we're creating a handler subclass FooHandler. It has two modes, a default
188 "foo" mode and an advanced "bar" mode. To allow both to be constructed by
189 stringified shortcuts, the FooHandler class implementation might start like
190 this:
191
192   package FooHandler;
193
194   use strict;
195   use App::Info::Handler;
196   use vars qw(@ISA);
197   @ISA = qw(App::Info::Handler);
198
199   foreach my $c (qw(foo bar)) {
200       App::Info::Handler->register_handler
201         ( $c => sub { __PACKAGE__->new( mode => $c) } );
202   }
203
204 The strings "foo" and "bar" can then be used by clients as shortcuts to have
205 App::Info objects automatically create and use handlers for certain events.
206 For example, if a client wanted to use a "bar" event handler for its info
207 events, it might do this:
208
209   use App::Info::Category::FooApp;
210   use FooHandler;
211
212   my $app = App::Info::Category::FooApp->new(on_info => ['bar']);
213
214 Take a look at App::Info::Handler::Print and App::Info::Handler::Carp to see
215 concrete examples of C<register_handler()> usage.
216
217 The final step in creating a new App::Info event handler is to implement the
218 C<handler()> method itself. This method takes a single argument, an
219 App::Info::Request object, and is expected to return true if it handled the
220 request, and false if it did not. The App::Info::Request object contains all
221 the metadata relevant to a request, including the type of event that triggered
222 it; see L<App::Info::Request|App::Info::Request> for its documentation.
223
224 Use the App::Info::Request object however you like to handle the request
225 however you like. You are, however, expected to abide by a a few guidelines:
226
227 =over 4
228
229 =item *
230
231 For error and info events, you are expected (but not required) to somehow
232 display the info or error message for the user. How your handler chooses to do
233 so is up to you and the handler.
234
235 =item *
236
237 For unknown and confirm events, you are expected to prompt the user for a
238 value. If it's a confirm event, offer the known value (found in
239 C<$req-E<gt>value>) as a default.
240
241 =item *
242
243 For unknown and confirm events, you are expected to call C<$req-E<gt>callback>
244 and pass in the new value. If C<$req-E<gt>callback> returns a false value, you
245 are expected to display the error message in C<$req-E<gt>error> and prompt the
246 user again. Note that C<$req-E<gt>value> calls C<$req-E<gt>callback>
247 internally, and thus assigns the value and returns true if
248 C<$req-E<gt>callback> returns true, and does not assign the value and returns
249 false if C<$req-E<gt>callback> returns false.
250
251 =item *
252
253 For unknown and confirm events, if you've collected a new value and
254 C<$req-E<gt>callback> returns true for that value, you are expected to assign
255 the value by passing it to C<$req-E<gt>value>. This allows App::Info to give
256 the value back to the calling App::Info concrete subclass.
257
258 =back
259
260 Probably the easiest way to get started creating new App::Info event handlers
261 is to check out the simple handlers provided with the distribution and follow
262 their logical examples. Consult the App::Info documentation of the L<event
263 methods|App::Info/"Events"> for details on how App::Info constructs the
264 App::Info::Request object for each event type.
265
266 =head1 BUGS
267
268 Report all bugs via the CPAN Request Tracker at
269 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=App-Info>.
270
271 =head1 AUTHOR
272
273 David Wheeler <L<david@wheeler.net|"david@wheeler.net">>
274
275 =head1 SEE ALSO
276
277 L<App::Info|App::Info> thoroughly documents the client interface for setting
278 event handlers, as well as the event triggering interface for App::Info
279 concrete subclasses.
280
281 L<App::Info::Request|App::Info::Request> documents the interface for the
282 request objects passed to App::Info::Handler C<handler()> methods.
283
284 The following App::Info::Handler subclasses offer examples for event handler
285 authors, and, of course, provide actual event handling functionality for
286 App::Info clients.
287
288 =over 4
289
290 =item L<App::Info::Handler::Carp|App::Info::Handler::Carp>
291
292 =item L<App::Info::Handler::Print|App::Info::Handler::Print>
293
294 =item L<App::Info::Handler::Prompt|App::Info::Handler::Prompt>
295
296 =back
297
298 =head1 COPYRIGHT AND LICENSE
299
300 Copyright (c) 2002, David Wheeler. All Rights Reserved.
301
302 This module is free software; you can redistribute it and/or modify it under the
303 same terms as Perl itself.
304
305 =cut