File Coverage

blib/lib/WebService/ISBNDB/Agent.pm
Criterion Covered Total %
statement 89 124 71.7
branch 10 28 35.7
condition 8 26 30.7
subroutine 25 35 71.4
pod 17 17 100.0
total 149 230 64.7


line stmt bran cond sub pod time code
1             ###############################################################################
2             #
3             # This file copyright (c) 2006-2008 by Randy J. Ray, all rights reserved
4             #
5             # See "LICENSE" in the documentation for licensing and redistribution terms.
6             #
7             ###############################################################################
8             #
9             # $Id: Agent.pm 47 2008-04-06 10:12:34Z $
10             #
11             # Description: This is the base class for all protocol agents. It provides
12             # the skeletal functionality and management of the LWP::UA
13             # instance.
14             #
15             # Functions: add_protocol
16             # BUILD
17             # class_for_protocol
18             # get_useragent
19             # new
20             # protocol
21             # raw_request
22             # remove_protocol
23             # request
24             # request_all
25             # request_body
26             # request_headers
27             # request_method
28             # request_single
29             # request_uri
30             # resolve_obj
31             # set_useragent
32             # _lr_trim
33             #
34             # Libraries: Class::Std
35             # Error
36             # LWP::UserAgent
37             # HTTP::Request
38             # URI
39             #
40             # Global Consts: $VERSION
41             #
42             ###############################################################################
43              
44             package WebService::ISBNDB::Agent;
45              
46 10     10   247 use 5.006;
  10         31  
  10         459  
47 10     10   68 use strict;
  10         93  
  10         336  
48 10     10   45 use warnings;
  10         14  
  10         317  
49 10     10   47 use vars qw($VERSION @PROTOS %PROTOS);
  10         17  
  10         699  
50 10     10   47 use base 'Class::Std';
  10         56  
  10         1439  
51 10     10   73 use constant COREPROTOS => qw(REST);
  10         20  
  10         794  
52              
53 10     10   125 use Error;
  10         17  
  10         55  
54 10     10   10870 use URI;
  10         50992  
  10         322  
55 10     10   12961 use LWP::UserAgent;
  10         618207  
  10         360  
56 10     10   103 use HTTP::Request;
  10         18  
  10         819  
57              
58             $VERSION = "0.30";
59              
60             BEGIN
61             {
62 10     10   40 @PROTOS = (COREPROTOS);
63 10         30 %PROTOS = map { $_ => __PACKAGE__ . "::$_" } @PROTOS;
  10         11291  
64             }
65              
66             my %useragent : ATTR(:init_arg :default<>);
67             my %agent_args : ATTR(:name :default<>);
68              
69             ##############################################################################
70             #
71             # Sub Name: new
72             #
73             # Description: Constructor for the class.
74             #
75             # Arguments: NAME IN/OUT TYPE DESCRIPTION
76             # $class in scalar The class to bless object into
77             # @argz in list Variable list of args, see text
78             #
79             # Globals: %TYPES
80             #
81             # Returns: Success: new object
82             # Failure: Throws Error::Simple
83             #
84             ###############################################################################
85             sub new
86             {
87 9     9 1 548 my ($class, @argz) = @_;
88 9         15 my ($proto, $self);
89              
90             # Need to make sure $class is the name, not a reference, for later tests:
91 9   33     53 $class = ref($class) || $class;
92              
93             # If $class matches this package, then they must specify a protocol
94             # as the leading argument (currently only 'REST')
95 9 50       31 if ($class eq __PACKAGE__)
96             {
97 9         28 $proto = uc shift(@argz);
98 9 100       42 throw Error::Simple("new: Unknown factory type '$proto'")
99             unless $class = $class->class_for_protocol($proto);
100             # Make sure it is loaded
101 4         255 eval "require $class;";
102             }
103 4   100     31 my $args = shift(@argz) || {};
104              
105 4 50       21 return $proto ? $class->new($args) : $class->SUPER::new($args);
106             }
107              
108             ###############################################################################
109             #
110             # Sub Name: BUILD
111             #
112             # Description: Class initializer.
113             #
114             # Arguments: NAME IN/OUT TYPE DESCRIPTION
115             # $self in ref Object
116             # $id in scalar Unique identifier for $self
117             # $args in hashref Current arguments for the
118             # constructor
119             #
120             # Returns: Success: void
121             # Failure: throws Error::Simple
122             #
123             ###############################################################################
124             sub BUILD
125             {
126 4     4 1 234 my ($self, $id, $args) = @_;
127              
128 4 50 0     14 throw Error::Simple("Value for 'useragent' must derive from LWP::UserAgent")
      33        
129             if ($args->{useragent} and
130             ! (ref($args->{useragent}) and $args->{useragent}->isa('LWP::UserAgent')));
131 4 50 66     24 throw Error::Simple("Value for 'agent_args' must be a hash reference")
132             if ($args->{agent_args} and (ref($args->{agent_args}) ne 'HASH'));
133              
134 4         9 return;
135             }
136              
137             ###############################################################################
138             #
139             # Sub Name: get_useragent
140             #
141             # Description: Retrieve the LWP::Agent object used by this object. Create
142             # it if it isn't already allocated.
143             #
144             # Arguments: NAME IN/OUT TYPE DESCRIPTION
145             # $self in ref Object
146             #
147             # Globals: %useragent
148             #
149             # Returns: Success: LWP::UserAgent isntance
150             # Failure: throws Error::Simple
151             #
152             ###############################################################################
153             sub get_useragent
154             {
155 5     5 1 1558 my $self = shift;
156 5         16 my $useragent = $useragent{ident $self};
157              
158 5 50       13 unless ($useragent)
159             {
160 5         10 my $useragent_args = $agent_args{ident $self};
161              
162 5         32 $useragent = LWP::UserAgent->new(%$useragent_args);
163             }
164              
165 5         3497 $useragent;
166             }
167              
168             ###############################################################################
169             #
170             # Sub Name: set_useragent
171             #
172             # Description: Assign a new useragent to the object. The agent must derive
173             # from LWP::UserAgent.
174             #
175             # Arguments: NAME IN/OUT TYPE DESCRIPTION
176             # $self in ref Object
177             # $agent in ref New agent object
178             #
179             # Globals: %useragent
180             #
181             # Returns: Success: $self
182             # Failure: throws Error::Simple
183             #
184             ###############################################################################
185             sub set_useragent
186             {
187 1     1 1 998 my ($self, $agent) = @_;
188              
189 1 0 0     5 throw Error::Simple("New agent must be derived from LWP::UserAgent")
      33        
190             unless (! defined $agent or
191             (ref($agent) and $agent->isa('LWP::UserAgent')));
192              
193 1         5 $useragent{ident $self} = $agent;
194              
195 1         2 $self;
196             }
197              
198             ###############################################################################
199             #
200             # Sub Name: add_protocol
201             #
202             # Description: Add a name-to-class mapping for the list of known Agent
203             # protocols.
204             #
205             # Arguments: NAME IN/OUT TYPE DESCRIPTION
206             # $class in scalar Ignored-- this can be a static
207             # method or not.
208             # $proto in scalar The protocol name, usually the
209             # last element of the classname
210             # all-lowercase (e.g. rest).
211             # $pack in scalar The package that should be
212             # instantiated for the protocol
213             #
214             # Globals: @PROTOS
215             # %PROTOS
216             #
217             # Returns: Success: $pack (for chaining purposes)
218             # Failure: Throws Error::Simple
219             #
220             ###############################################################################
221             sub add_protocol
222             {
223 2     2 1 1004 my ($class, $proto, $pack) = @_;
224              
225 2         5 $proto = uc $proto;
226 2 50       6 throw Error::Simple("No package specfied for $proto") unless $pack;
227              
228 2         4 push(@PROTOS, $proto);
229 2         8 $PROTOS{$proto} = $pack;
230             }
231              
232             ###############################################################################
233             #
234             # Sub Name: remove_protocol
235             #
236             # Description: Delete the given protocol from the map.
237             #
238             # Arguments: NAME IN/OUT TYPE DESCRIPTION
239             # $class in scalar Ignored-- this can be a static
240             # method or not.
241             # $proto in scalar The protocol name, usually the
242             # last element of the classname
243             # in all-lowercase (e.g. rest).
244             #
245             # Globals: @PROTOS
246             # %PROTOS
247             # @COREPROTOS
248             #
249             # Returns: Success: void
250             # Failure: throws Error::Simple if $proto in @COREPROTOS
251             #
252             ###############################################################################
253             sub remove_protocol
254             {
255 2     2 1 784 my ($class, $proto) = @_;
256              
257 2 100       24 throw Error::Simple("Cannot remove a core protocol")
258             if (grep($_ eq $proto, (COREPROTOS)));
259 1         3 delete $PROTOS{$proto};
260 1         5 @PROTOS = grep($_ ne $proto, @PROTOS);
261              
262 1         2 return;
263             }
264              
265             ###############################################################################
266             #
267             # Sub Name: class_for_protocol
268             #
269             # Description: Return the actual class that should be used to instantiate
270             # the given protocol.
271             #
272             # Arguments: NAME IN/OUT TYPE DESCRIPTION
273             # $class in scalar Ignored-- this can be a static
274             # method or not.
275             # $proto in scalar Protocol to look up.
276             #
277             # Globals: %PROTOS
278             #
279             # Returns: Success: class name
280             # Failure: undef
281             #
282             ###############################################################################
283             sub class_for_protocol
284             {
285 12     12 1 28 my ($class, $proto) = @_;
286              
287 12         122 $PROTOS{$proto};
288             }
289              
290             ###############################################################################
291             #
292             # Sub Name: protocol
293             #
294             # Description: For the implementation classes, this should either return
295             # a string identifying the protocol, or if passed a string
296             # should return a true/false whether the class matches that
297             # protocol.
298             #
299             # In this package, it just throws an exception, to remind you
300             # to override it in the implementation class.
301             #
302             # Arguments: NAME IN/OUT TYPE DESCRIPTION
303             # $self in ref Object
304             #
305             # Returns: This version just throws Error::Simple
306             #
307             ###############################################################################
308             sub protocol
309             {
310 1     1 1 2 my $self = shift;
311 1   33     7 my $class = ref($self) || $self;
312              
313 1         9 throw Error::Simple("Package $class has not overridden the protocol() " .
314             "method");
315             }
316              
317             ###############################################################################
318             #
319             # Sub Name: request_single
320             #
321             # Description: Make a request, returning a single result object.
322             #
323             # Arguments: NAME IN/OUT TYPE DESCRIPTION
324             # $self in ref Object
325             # $obj in ref Object from the API hierarchy
326             # $args in hashref Arguments to the request
327             #
328             # Returns: Success: object reference
329             # Failure: throws Error::Simple
330             #
331             ###############################################################################
332             sub request_single
333             {
334 0     0 1   my ($self, $obj, $args) = @_;
335              
336 0           $self->request($obj, $args)->first;
337             }
338              
339             ###############################################################################
340             #
341             # Sub Name: request_all
342             #
343             # Description: Make a request, returning all the matching records as
344             # objects, in an Iterator instance.
345             #
346             # Arguments: NAME IN/OUT TYPE DESCRIPTION
347             #
348             # $self in ref Object
349             # $obj in ref Object from the API hierarchy
350             # $args in hashref Arguments to the request
351             #
352             # Returns: Success: array reference
353             # Failure: throws Error::Simple
354             #
355             ###############################################################################
356             sub request_all
357             {
358 0     0 1   my ($self, $obj, $args) = @_;
359              
360 0           $self->request($obj, $args);
361             }
362              
363             ###############################################################################
364             #
365             # Sub Name: request_method
366             #
367             # Description: Return the HTTP request method needed for sending the
368             # request to the service.
369             #
370             # Arguments: NAME IN/OUT TYPE DESCRIPTION
371             # $self in ref Object
372             # $obj in ref Object from the API hierarchy
373             # $args in hashref Arguments to the request
374             #
375             # Returns: null string
376             #
377             ###############################################################################
378             sub request_method : RESTRICTED
379             {
380 0     0 1 0 '';
381 10     10   64 }
  10         17  
  10         133  
382              
383             ###############################################################################
384             #
385             # Sub Name: request_uri
386             #
387             # Description: Return the URL to which the request should be sent, as an
388             # object of the URI class.
389             #
390             # Arguments: NAME IN/OUT TYPE DESCRIPTION
391             # $self in ref Object
392             # $obj in ref Object from the API hierarchy
393             # $args in hashref Arguments to the request
394             #
395             # Returns: null URI object
396             #
397             ###############################################################################
398             sub request_uri : RESTRICTED
399             {
400 0     0 1 0 URI->new();
401 10     10   8814 }
  10         29  
  10         43  
402              
403             ###############################################################################
404             #
405             # Sub Name: request_headers
406             #
407             # Description: Return any additional headers (besides the default ones
408             # set up by HTTP::Request and LWP::UserAgent) needed for the
409             # request, as an array reference.
410             #
411             # Arguments: NAME IN/OUT TYPE DESCRIPTION
412             # $self in ref Object
413             # $obj in ref Object from the API hierarchy
414             # $args in hashref Arguments to the request
415             #
416             # Returns: empty array reference
417             #
418             ###############################################################################
419             sub request_headers : RESTRICTED
420             {
421 0     0 1 0 [];
422 10     10   1863 }
  10         37  
  10         43  
423              
424             ###############################################################################
425             #
426             # Sub Name: request_body
427             #
428             # Description: Return the body-content of the request, as a scalar
429             # reference.
430             #
431             # Arguments: NAME IN/OUT TYPE DESCRIPTION
432             # $self in ref Object
433             # $obj in ref Object from the API hierarchy
434             # $args in hashref Arguments to the request
435             #
436             # Returns: empty scalar reference
437             #
438             ###############################################################################
439             sub request_body : RESTRICTED
440             {
441 0     0 1 0 \'';
442 10     10   1669 }
  10         20  
  10         79  
443              
444             ###############################################################################
445             #
446             # Sub Name: resolve_obj
447             #
448             # Description: Decide what value to use within request_single() and
449             # request_all(), based on the disposition of $obj.
450             #
451             # Arguments: NAME IN/OUT TYPE DESCRIPTION
452             # $self in ref Object
453             # $obj in scalar Input from the user, to be
454             # resolved
455             #
456             # Returns: Success: value to use
457             # Failure: throws Error::Simple
458             #
459             ###############################################################################
460             sub resolve_obj : RESTRICTED
461             {
462 0     0 1 0 my ($self, $obj) = @_;
463 0         0 my $retval;
464              
465             # Is it already a usable object?
466 0 0       0 if ($obj->isa('WebService::ISBNDB::API'))
    0          
467             {
468             # This actually catches two of the cases, ref($obj) and $obj being
469             # the name of a class that qualifies.
470 0         0 $retval = $obj;
471             }
472             elsif (my $tmp = WebService::ISBNDB::API->class_for_type($obj))
473             {
474 0         0 $retval = $tmp;
475             }
476             else
477             {
478             # No dice
479 0         0 throw Error::Simple("Value ($obj) not valid for operation");
480             }
481              
482 0         0 $retval;
483 10     10   2526 }
  10         29  
  10         39  
484              
485             ###############################################################################
486             #
487             # Sub Name: request
488             #
489             # Description: Stub for the request method that subclasses must override.
490             #
491             # Returns: throws Error::Simple
492             #
493             ###############################################################################
494             sub request
495             {
496 0   0 0 1   throw Error::Simple((ref($_[0]) || $_[0]) . ' did not override request()');
497             }
498              
499             ###############################################################################
500             #
501             # Sub Name: raw_request
502             #
503             # Description: Do the actual work of creating and dispatching the HTTP
504             # request. Return the body of the response as a scalar
505             # reference. This allows request_single() and request_all()
506             # to share this part of the logic and focus on their specific
507             # functions.
508             #
509             # Arguments: NAME IN/OUT TYPE DESCRIPTION
510             # $self in ref Object
511             # $obj in ref Object from the API hierarchy
512             # $args in hashref Arguments to the request
513             #
514             # Returns: Success: scalar reference
515             # Failure: throws Error::Simple
516             #
517             ###############################################################################
518             sub raw_request : RESTRICTED
519             {
520 0     0 1 0 my ($self, $obj, $args) = @_;
521              
522             # Resolve $obj before using it to call the other methods
523 0         0 $obj = $self->resolve_obj($obj);
524              
525 0         0 my $method = $self->request_method($obj, $args);
526 0         0 my $uri = $self->request_uri($obj, $args);
527 0         0 my $headers = $self->request_headers($obj, $args);
528 0         0 my $body = $self->request_body($obj, $args);
529              
530             # We have to have at least a method and a URI, so check those:
531 0 0       0 throw Error::Simple("Cannot make a request without a HTTP method (Did " .
532             "you remember to override request_method()?)")
533             unless $method;
534 0 0       0 throw Error::Simple("Cannot make a request without a HTTP URL (Did " .
535             "you remember to override request_uri()?)")
536             unless $uri;
537              
538 0         0 my $request = HTTP::Request->new($method, $uri, $headers, $$body);
539 0         0 my $UA = $self->get_useragent;
540              
541             # Make the request, check for problems
542 0         0 my $response = $UA->request($request);
543 0 0       0 throw Error::Simple("Error from HTTP request: " . $response->message)
544             if ($response->is_error);
545              
546 0         0 my $anon = $response->content;
547 0         0 \$anon;
548 10     10   4283 }
  10         17  
  10         225  
549              
550             ###############################################################################
551             #
552             # Sub Name: _lr_trim
553             #
554             # Description: Do a right- and left-trim of whitespace and newlines off of
555             # the passed-in string. Also translate newlines and returns
556             # within a string to spaces, and squeeze sequences of spaces.
557             #
558             # Arguments: NAME IN/OUT TYPE DESCRIPTION
559             # $class in scalar Ignored
560             # $string in scalar String to trim
561             #
562             # Returns: Trimmed string
563             #
564             ###############################################################################
565             sub _lr_trim
566             {
567 0     0     my ($class, $string) = @_;
568              
569 0           $string =~ tr/\n\r\t / /s;
570 0           $string =~ s/^[\s\n]*//;
571 0           $string =~ s/[\s\n]*$//;
572              
573 0           $string;
574             }
575              
576             1;
577              
578             =pod
579              
580             =head1 NAME
581              
582             WebService::ISBNDB::Agent - Base class for data-retrieval agents
583              
584             =head1 SYNOPSIS
585              
586             package WebService::ISBNDB::Agent::REST;
587              
588             use strict;
589             use warnings;
590             use base 'WebService::ISBNDB::Agent';
591              
592             =head1 DESCRIPTION
593              
594             The B class is a base class for all the classes
595             that provide actual communication protocol support for the
596             B module. Unlike the API class, this class is not
597             usable on its own except as a factory to create instances of classes that
598             derive from it.
599              
600             The agent classes are responsible for actually setting up the web requests
601             to retrieve data, parsing the results of those calls, and returning the
602             data in formats usable by the API classes.
603              
604             This class (and all sub-classes of it) are based on the B
605             inside-out objects pattern. See L for more detail.
606              
607             All error conditions in the methods of this class are handled using the
608             exception model provided by the B module. Most errors are thrown in
609             the form of B exception objects. See L for more
610             detail.
611              
612             =head1 METHODS
613              
614             The following methods are implemented (or in some cases, stubbed) in this
615             base class. In some cases, the method requires that an implementation class
616             override it in order to work. This is noted when it applies.
617              
618             =head2 Constructor
619              
620             The constructor for this class should only ever be called to act as a factory
621             constructor. Instantiating this class directly is not permitted, and will
622             cause an exception to be thrown.
623              
624             =over 4
625              
626             =item new($PROTO [ , $ARGS ])
627              
628             Create a new object of the specified protocol and return a referent to it.
629             If C<$args> is passed, it is passed along to the protocol class' constructor.
630             If the protocol referred to by C<$PROTO> is unknown, or if C<$PROTO> is not
631             passed, an exception will be thrown.
632              
633             =back
634              
635             =head2 Accessors
636              
637             The accessor methods are used to set and retrieve the attributes (instance
638             data) stored on the object. While a few of them have special behavior, most
639             operate as simple get or set accessors as described in L. The
640             attributes for this class are:
641              
642             =over 4
643              
644             =item useragent
645              
646             The user-agent (an instance or derivative of B) used to make
647             all the HTTP requests to the service. Unless explicitly provided by the user,
648             this value is not initialized until the first request made to it. The next
649             attribute allows the user to specify arguments to the constructor when the
650             object is finally instantiated.
651              
652             =item agent_args
653              
654             A hash reference of parameters to be passed to the constructor of the agent
655             when it is created. The B constructor takes ordinary
656             key/value pairs as arguments, not a single hash reference like classes
657             derived from B. This value will be "flattened" when the
658             constructor is called. Value within it, however, will not be. You must make
659             certain that the values for any keys specified match the expected format
660             within B.
661              
662             =back
663              
664             The following accessor methods are provided by this class:
665              
666             =over 4
667              
668             =item get_useragent
669              
670             Retrieve the user-agent this object uses for HTTP communication. The creation
671             of this object is delayed until the first request to fetch it (unless the
672             user has explicitly set the agent, or provided an agent in the construction
673             of the B-derived object).
674              
675             =item set_useragent($AGENT)
676              
677             Explicitly set the user-agent for this object to use. The new value must be
678             an instance of B, or an object of a class that is derived
679             from that one. If it isn't, an exception will be thrown.
680              
681             =item get_agent_args
682              
683             Get the current value of the arguments used in the creation of a user-agent
684             instance. If none have been set, the value returned will be C.
685              
686             =item set_agent_args($ARGS)
687              
688             Set a new hash reference of arguments to be used when the user-agent is
689             instantiated. Note that the object will instantiate the user-agent at most
690             once, so setting this after the first call to B (or after
691             explicitly setting the agent attribute) will have no effect. The value of
692             C<$ARGS> must be a hash reference, or an exception will be thrown.
693              
694             =back
695              
696             =head2 Managing Protocols
697              
698             For communication protocols, the only built-in protocol is:
699              
700             =over 4
701              
702             =item REST
703              
704             The web services protocol known as C, this
705             protocol uses the URL exclusively for data-fetch operations (which, since
706             B is a read-only source, is all this module does). All parameters
707             for searches and data retrieval are passed as query parameters in the URL in
708             the request.
709              
710             =back
711              
712             All protocol names are treated as upper-case strings. The values are forced
713             to upper-case within the following methods:
714              
715             =over 4
716              
717             =item add_protocol($PROTO, $CLASS)
718              
719             Add a mapping of the new protocol specified by C<$PROTO> to the class given
720             as C<$CLASS>. As with types, you can use this to override the class that will
721             be instantiated for any of the built-in protocols. You cannot delete mappings
722             for any core protocols, so if you wish to temporarily override the class,
723             you must save the existing map value (with B, below) and
724             re-assign it yourself.
725              
726             =item class_for_protocol($PROTO)
727              
728             Returns the class-name for the given protocol. If C<$PROTO> is not know, then
729             an exception (of type B ) is thrown.
730              
731             =item remove_protocol($PROTO)
732              
733             Removes the mapping for C<$PROTO> from the internal table. You cannot remove
734             the mapping for a core protocol (an exception will be thrown if you try to).
735             You can only override it with another call to B.
736              
737             =item protocol([$PROTO])
738              
739             Return the protocol this object implements, or test a given string to see if
740             to matches the implemented protocol. If C<$PROTO> is passed in, the method
741             will return either a true or false value, depending on whether the value
742             matches the protocol of this object. If C<$PROTO> is not passed in, the
743             return value is a string representation of the module's protocol.
744              
745             =back
746              
747             The protocol-oriented methods are intended for the future, if/when
748             B should offer other methods besides REST. These class methods
749             can be used by separate modules to register their protocols with this
750             class.
751              
752             As with the type-map methods in B, all of the
753             protocol-map methods may be called as static methods.
754              
755             =head2 Making Requests
756              
757             The role of the agent classes is to make the requests for data from the
758             B service, parse the body of the response and convert that data to
759             objects from the B hierarchy. To do this, this base
760             class provides methods for making the requests, which themselves are composed
761             of several methods restricted to the B hierarchy.
762              
763             The methods are:
764              
765             =over 4
766              
767             =item request_single($OBJ, $ARGS)
768              
769             Make a request of the service, returning a single object as a result. C<$OBJ>
770             controls the type of object returned, as well as the type of request sent.
771             C<$OBJ> can be one of three types of values:
772              
773             =over 4
774              
775             =item B-derived object
776              
777             If the value is an object from one of the API classes (excluding
778             B itself), it is used not only to control the type of
779             request, but it is also overwritten with the result of the request. It is
780             also the return value of the call when successful.
781              
782             =item Type name
783              
784             If the value is a type recognized by the B class, the
785             class itself is retrieved via the B method. That class is used
786             to provide the type-specific data that would otherwise be retrieved through an
787             existing object, and it is used to instantiate the new object with the data
788             returned by the request.
789              
790             =item Class name
791              
792             If the value is a full class name, it is first tested to see that the class is
793             a decendant of B. If so, it is used in the same way
794             as the class derived from the previous case.
795              
796             =back
797              
798             The C<$ARGS> parameter provides the arguments used in making the specific
799             request. It is a hash reference, whose keys and values are dependent on the
800             specific implementation class.
801              
802             If the request returns more than one value, the first one is taken and the
803             rest are discarded. If the request returns no data, C is returned. If
804             there is an error of any sort, an exception is thrown.
805              
806             =item request_all($OBJ, $ARGS)
807              
808             This method sends the request, and returns all the resulting records from
809             the service. The arguments and behavior are identical to that of
810             C, except that the return value includes all records returned
811             by the query.
812              
813             Presently, the return value for a successful query is an array reference
814             containing the objects representing the matched records. This reference may
815             contain only one object, or even none, depending on whether the query
816             returned any data. In future versions, the return value will be an iterator
817             that manages the list internally, for faster response time and better memory
818             usage.
819              
820             =item resolve_obj($OBJ) (R)
821              
822             Resolves the disposition of the argument C<$OBJ>. This is what gets called by
823             B and B to determine how to interpret the first
824             argument.
825              
826             This method is restricted to the B class and its
827             decendents.
828              
829             =item raw_request($OBJ, $ARGS) (R)
830              
831             This method is what gets called to actually assemble the request from the
832             next four methods, make the request, and return the content. In this class,
833             the return value is a scalar reference to the content of the HTTP response.
834             In case of error (either from information missing from the following methods
835             or from HTTP communication failure), an exception is thrown. No parsing of the
836             content is done by this method.
837              
838             This method is restricted to the B class and its
839             decendents.
840              
841             =item request($OBJ, $ARGS [ , $SINGLE ]) (R)
842              
843             This method I be overridden in the protocol implementation class. If
844             the base class version is called, it will always throw an exception.
845              
846             This method is expected to fetch the content from B, above,
847             and return a suitable object created from the content. The C<$OBJ> and
848             C<$ARGS> parameters are the same as for B and B.
849             The optional argument C<$SINGLE> signifies that the request should only return
850             a single object, not a list of all objects returned by the service.
851              
852             This method is restricted to the B class and its
853             decendents.
854              
855             =item request_method($OBJ, $ARGS) (R)
856              
857             Returns the type of HTTP request (C or C) that should be used in
858             making the request, as a string. Throws an exception in case of error. The
859             An exception is thrown in case of error (such as C<$OBJ> not being valid). The
860             C<$OBJ> and C<$ARGS> parameters fulfill the same roles as defined for
861             B.
862              
863             This method is restricted to the B class and its
864             decendents.
865              
866             =item request_uri($OBJ, $ARGS) (R)
867              
868             Returns the complete URL to use in making the request, as a B instance.
869             An exception is thrown in case of error (such as C<$OBJ> not being valid). The
870             C<$OBJ> and C<$ARGS> parameters fulfill the same roles as defined for
871             B.
872              
873             This method is restricted to the B class and its
874             decendents.
875              
876             =item request_headers($OBJ, $ARGS) (R)
877              
878             Returns an array reference of any additional headers needed for the request.
879             The format is a series of values in key/value order. The reference may be an
880             empty array, if no additional headers are needed. An exception is thrown if
881             there is an error. The C<$OBJ> and C<$ARGS> parameters are the same as defined
882             for B.
883              
884             This method is restricted to the B class and its
885             decendents.
886              
887             =item request_body($OBJ, $ARGS) (R)
888              
889             Returns the request body needed for making the request, as a scalar reference.
890             The scalar may be zero-length, if no data is needed in the request body. An
891             exception is thrown if there is an error. The arguments are the same as for
892             B (and all the other methods in this group).
893              
894             This method is restricted to the B class and its
895             decendents.
896              
897             =back
898              
899             All of the request-construction methods (request_uri(), request_headers(),
900             request_body() and request_method()) return no content (or null content) from
901             their versions in this class.
902             It is expected that implementation classes will override those that need to
903             have content (certainly B and B), and leave
904             those that are not relevant to the protocol (REST, for example, does not need
905             a request body or additional headers).
906              
907             =head1 SEE ALSO
908              
909             L, L,
910             L, L
911              
912             =head1 AUTHOR
913              
914             Randy J. Ray Erjray@blackperl.comE
915              
916             =head1 LICENSE
917              
918             This module and the code within are
919             released under the terms of the Artistic License 2.0
920             (http://www.opensource.org/licenses/artistic-license-2.0.php). This
921             code may be redistributed under either the Artistic License or the GNU
922             Lesser General Public License (LGPL) version 2.1
923             (http://www.opensource.org/licenses/lgpl-license.php).
924              
925             =cut