summaryrefslogtreecommitdiff
path: root/lib/Net/Amazon
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Net/Amazon')
-rw-r--r--lib/Net/Amazon/Attribute/Review.pm104
-rw-r--r--lib/Net/Amazon/Attribute/ReviewSet.pm137
-rw-r--r--lib/Net/Amazon/Property.pm320
-rw-r--r--lib/Net/Amazon/Property/Book.pm152
-rw-r--r--lib/Net/Amazon/Property/DVD.pm156
-rw-r--r--lib/Net/Amazon/Property/Music.pm161
-rw-r--r--lib/Net/Amazon/Request.pm221
-rw-r--r--lib/Net/Amazon/Request/ASIN.pm139
-rw-r--r--lib/Net/Amazon/Request/Artist.pm86
-rw-r--r--lib/Net/Amazon/Request/Blended.pm80
-rw-r--r--lib/Net/Amazon/Request/BrowseNode.pm137
-rw-r--r--lib/Net/Amazon/Request/Exchange.pm91
-rw-r--r--lib/Net/Amazon/Request/Keyword.pm90
-rw-r--r--lib/Net/Amazon/Request/Manufacturer.pm78
-rw-r--r--lib/Net/Amazon/Request/Power.pm95
-rw-r--r--lib/Net/Amazon/Request/Seller.pm84
-rw-r--r--lib/Net/Amazon/Request/Similar.pm95
-rw-r--r--lib/Net/Amazon/Request/Sort.pm246
-rw-r--r--lib/Net/Amazon/Request/TextStream.pm76
-rw-r--r--lib/Net/Amazon/Request/UPC.pm94
-rw-r--r--lib/Net/Amazon/Request/Wishlist.pm89
-rw-r--r--lib/Net/Amazon/Response.pm214
-rw-r--r--lib/Net/Amazon/Response/ASIN.pm28
-rw-r--r--lib/Net/Amazon/Response/Artist.pm29
-rw-r--r--lib/Net/Amazon/Response/Blended.pm73
-rw-r--r--lib/Net/Amazon/Response/BrowseNode.pm29
-rw-r--r--lib/Net/Amazon/Response/Exchange.pm81
-rw-r--r--lib/Net/Amazon/Response/Keyword.pm29
-rw-r--r--lib/Net/Amazon/Response/Manufacturer.pm29
-rw-r--r--lib/Net/Amazon/Response/Power.pm28
-rw-r--r--lib/Net/Amazon/Response/Seller.pm78
-rw-r--r--lib/Net/Amazon/Response/Similar.pm28
-rw-r--r--lib/Net/Amazon/Response/TextStream.pm28
-rw-r--r--lib/Net/Amazon/Response/UPC.pm40
-rw-r--r--lib/Net/Amazon/Response/Wishlist.pm29
-rw-r--r--lib/Net/Amazon/Result/Seller.pm130
-rw-r--r--lib/Net/Amazon/Result/Seller/Listing.pm146
37 files changed, 3750 insertions, 0 deletions
diff --git a/lib/Net/Amazon/Attribute/Review.pm b/lib/Net/Amazon/Attribute/Review.pm
new file mode 100644
index 0000000..5a5d094
--- /dev/null
+++ b/lib/Net/Amazon/Attribute/Review.pm
@@ -0,0 +1,104 @@
+######################################################################
+package Net::Amazon::Attribute::Review;
+######################################################################
+use warnings;
+use strict;
+use Log::Log4perl qw(:easy);
+use base qw(Net::Amazon);
+
+__PACKAGE__->make_accessor($_) for qw(rating summary comment);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = {
+ rating => "",
+ summary => "",
+ comment => "",
+ %options,
+ };
+
+ bless $self, $class;
+}
+
+##################################################
+sub init_via_xmlref {
+##################################################
+ my($self, $xmlref) = @_;
+
+ for(qw(Rating Summary Comment)) {
+ my $method = lc($_);
+ if($xmlref->{$_}) {
+ $self->$method($xmlref->{$_});
+ } else {
+ #LOGWARN "No '$_'";
+ return undef;
+ }
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Attribute::Review - Customer Review Class
+
+=head1 SYNOPSIS
+
+ use Net::Amazon::Attribute::Review;
+ my $rev = Net::Amazon::Attribute::Review->new(
+ 'rating' => $rating,
+ 'summary' => $summary,
+ 'comment' => $comment,
+ );
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Attribute::Review> holds customer reviews.
+
+=head2 METHODS
+
+=over 4
+
+=item rating()
+
+Accessor for the numeric value of the rating.
+
+=item summary()
+
+Accessor for the string value of the summary.
+
+=item comment()
+
+Accessor for the string value of the customer comment.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+__END__
+ <Reviews>
+ <AvgCustomerRating>4.33</AvgCustomerRating>
+ <TotalCustomerReviews>6</TotalCustomerReviews>
+ <CustomerReview>
+ <Rating>4</Rating>
+ <Summary>Good introduction to Perl, and great reference</Summary>
+ <Comment>From its corny title you might expect another one of those
+
diff --git a/lib/Net/Amazon/Attribute/ReviewSet.pm b/lib/Net/Amazon/Attribute/ReviewSet.pm
new file mode 100644
index 0000000..29a34e6
--- /dev/null
+++ b/lib/Net/Amazon/Attribute/ReviewSet.pm
@@ -0,0 +1,137 @@
+######################################################################
+package Net::Amazon::Attribute::ReviewSet;
+######################################################################
+use warnings;
+use strict;
+use Log::Log4perl qw(:easy);
+use Net::Amazon::Attribute::Review;
+use base qw(Net::Amazon);
+
+__PACKAGE__->make_accessor($_) for qw(average_customer_rating total_reviews);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = {
+ reviews => [], # list of reviews
+ };
+
+ bless $self, $class;
+}
+
+###########################################
+sub add_review {
+###########################################
+ my($self, $review) = @_;
+
+ if(ref $review ne "Net::Amazon::Attribute::Review") {
+ warn "add_review called with type ", ref $review;
+ return undef;
+ }
+
+ push @{$self->{reviews}}, $review;
+}
+
+###########################################
+sub reviews {
+###########################################
+ my($self) = @_;
+
+ return @{$self->{reviews}};
+}
+
+##################################################
+sub init_via_xmlref {
+##################################################
+ my($self, $xmlref) = @_;
+
+ my @pairs = qw(AvgCustomerRating average_customer_rating
+ TotalCustomerReviews total_reviews);
+
+ while(my($field, $method) = splice @pairs, 0, 2) {
+
+ if(defined $xmlref->{$field}) {
+ DEBUG "Setting $field via $method to $xmlref->{$field}";
+ $self->$method($xmlref->{$field});
+ } else {
+ LOGWARN "No '$field'";
+ return undef;
+ }
+ }
+
+ if(ref $xmlref->{CustomerReview} ne "ARRAY") {
+ $xmlref->{CustomerReview} = [$xmlref->{CustomerReview}];
+ }
+
+ for my $review_xmlref (@{$xmlref->{CustomerReview}}) {
+ my $review = Net::Amazon::Attribute::Review->new();
+ $review->init_via_xmlref($review_xmlref);
+ DEBUG "Adding review ", $review->summary();
+ $self->add_review($review);
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Attribute::ReviewSet - A set of customer reviews
+
+=head1 SYNOPSIS
+
+ use Net::Amazon::Attribute::ReviewSet;
+ my $rev = Net::Amazon::Attribute::Review->new(
+ average_customer_rating => $avg,
+ total_reviews => $total,
+ );
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Attribute::ReviewSet> holds a list of customer
+reviews, each of type C<Net::Amazon::Attribute::Review>.
+
+=head2 METHODS
+
+=over 4
+
+=item C<< $self->reviews() >>
+
+Returns a list of C<Net::Amazon::Attribute::Review> objects.
+
+=item C<< $self->average_customer_rating() >>
+
+Accessor for the average customer rating, a numeric value.
+
+=item C<< $self->total_reviews() >>
+
+Accessor for the total number of reviews. Please note that this
+might not be equal to the number of reviews held in the list, since
+there might be less customer reviews than total reviews (reviews
+can also be non-customer-reviews, but they're not available by
+the web service as of Aug 2003).
+
+=item C<< $self->add_review($rev) >>
+
+Add a C<Net::Amazon::Attribute::Review> object to the list.
+(Used internally only).
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Property.pm b/lib/Net/Amazon/Property.pm
new file mode 100644
index 0000000..6c06957
--- /dev/null
+++ b/lib/Net/Amazon/Property.pm
@@ -0,0 +1,320 @@
+######################################################################
+package Net::Amazon::Property;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon);
+
+use Net::Amazon::Property::DVD;
+use Net::Amazon::Property::Book;
+use Net::Amazon::Property::Music;
+use Net::Amazon::Attribute::ReviewSet;
+use Data::Dumper;
+use Log::Log4perl qw(:easy);
+
+use warnings;
+use strict;
+
+our @DEFAULT_ATTRIBUTES = qw(
+ OurPrice ImageUrlLarge ImageUrlMedium ImageUrlSmall
+ ReleaseDate Catalog Asin url Manufacturer UsedPrice
+ ListPrice ProductName Availability SalesRank
+ Media NumMedia ProductDescription
+ CollectiblePrice CollectibleCount NumberOfOfferings
+ UsedCount ThirdPartyNewPrice ThirdPartyNewCount
+ ThirdPartyProductInfo
+);
+
+__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES;
+__PACKAGE__->make_accessor($_) for qw(year review_set);
+__PACKAGE__->make_array_accessor($_) for qw(browse_nodes similar_asins);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ if(!$options{xmlref}) {
+ die "Mandatory param xmlref missing";
+ }
+
+ my $self = {
+ %options,
+ };
+
+ bless $self, $class;
+
+ # Set default attributes
+ for my $attr (@DEFAULT_ATTRIBUTES) {
+ $self->$attr($options{xmlref}->{$attr});
+ }
+
+ # The release date is sometimes missing
+ if($options{xmlref}->{ReleaseDate}) {
+ my ($year) = ($options{xmlref}->{ReleaseDate} =~ /(\d{4})/);
+ $self->year($year);
+ } else {
+ $self->year("");
+ }
+
+ my $browse_nodes = $options{xmlref}->{BrowseList}->{BrowseNode};
+ if(ref($browse_nodes) eq "ARRAY") {
+ my @nodes = map {
+ $_->{BrowseName}
+ } @{ $browse_nodes };
+ $self->browse_nodes(\@nodes);
+ } elsif (ref($browse_nodes) eq "HASH") {
+ $self->browse_nodes([ $browse_nodes->{BrowseName} ]);
+ } else {
+ $self->browse_nodes([ ]);
+ }
+
+ my $similar = $options{xmlref}->{SimilarProducts};
+ if(ref($similar) eq "HASH") {
+ $self->similar_asins($similar->{Product});
+ } else {
+ $self->similar_asins([ ]);
+ }
+
+ return $self;
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ my $result = "\"$self->{xmlref}->{ProductName}\", ";
+
+ if($self->{xmlref}->{Manufacturer}) {
+ $result .= "$self->{xmlref}->{Manufacturer}, ";
+ }
+
+ $result .= $self->year() . ", " if $self->year();
+
+ $result .= $self->OurPrice() . ", ";
+ $result .= $self->Asin();
+ return $result;
+}
+
+##################################################
+sub factory {
+##################################################
+ my(%options) = @_;
+
+ my $xmlref = $options{xmlref};
+ die "Called factory without xmlref" unless $xmlref;
+
+ # DEBUG(sub {"factory xmlref=" . Data::Dumper::Dumper($xmlref)});
+
+ my $catalog = $xmlref->{Catalog};
+ my $obj;
+
+ if(0) {
+ } elsif($catalog eq "Book") {
+ DEBUG("Creating new Book Property");
+ $obj = Net::Amazon::Property::Book->new(xmlref => $xmlref);
+ } elsif($catalog eq "Music") {
+ DEBUG("Creating new Music Property");
+ $obj = Net::Amazon::Property::Music->new(xmlref => $xmlref);
+ } elsif($catalog eq "DVD") {
+ DEBUG("Creating new DVD Property");
+ $obj = Net::Amazon::Property::DVD->new(xmlref => $xmlref);
+ } else {
+ DEBUG("Creating new Default Property ($catalog)");
+ $obj = Net::Amazon::Property->new(xmlref => $xmlref);
+ }
+
+ return $obj;
+}
+
+##################################################
+sub init_via_xmlref {
+##################################################
+ my($self, $xmlref) = @_;
+
+ my $reviewset = Net::Amazon::Attribute::ReviewSet->new();
+
+ if(exists $xmlref->{Reviews}) {
+ $reviewset->init_via_xmlref($xmlref->{Reviews});
+ }
+
+ $self->review_set($reviewset);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Property - Baseclass for products on amazon.com
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+
+ # ...
+
+ if($resp->is_success()) {
+ for my $prop ($resp->properties) {
+ print $_->ProductName(), " ",
+ $_->Manufacturer(), " ",
+ $_->OurPrice(), "\n";
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Property> is the baseclass for results returned
+from Amazon web service queries. The term 'properties' is used as
+a generic description for an item on amazon.com.
+
+Typically, the C<properties()> method of a C<Net::Amazon::Response::*> object
+will return one or more objects of class C<Net::Amazon::Property> or
+one of its subclasses, e.g. C<Net::Amazon::Property::Book> or
+C<Net::Amazon::Property::CD>.
+
+While C<Net::Amazon::Property> objects expose accessors for all
+fields returned in the XML response (like C<OurPrice()>, C<ListPrice()>,
+C<Manufacturer()>, C<Asin()>, C<Catalog()>, C<ProductName()>, subclasses
+might define their own accessors to more class-specific fields
+(like the iC<Net::Amazon::Property::Book>'s C<authors()> method returning
+a list of authors, while C<Net::Amazon::Property>'s C<Authors()> method
+will return a reference to a sub-hash containing a C<Author> field, just like
+the response's XML contained it).
+
+=head2 METHODS
+
+Methods vary, depending on the item returned from a query. Here's the most
+common ones. They're all accessors, meaning they can be used like C<Method()>
+to retrieve the value or like C<Method($value)> to set the value of the
+field.
+
+=over 4
+
+=item Asin()
+
+The item's ASIN number.
+
+=item ProductName()
+
+Book title, CD album name or item name
+
+=item Availability()
+
+Text string describing if the item is available. Examples:
+C<"Usually ships within 24 hours"> or
+C<"Out of Print--Limited Availability">.
+
+=item Catalog()
+
+Shows the catalog the item was found in: C<Book>, C<Music>, C<Classical>,
+C<Electronics> etc.
+
+=item Authors()
+
+Returns a sub-hash with a C<Author> key, which points to either a single
+$scalar or to a reference of an array containing author names as scalars.
+
+=item ReleaseDate()
+
+Item's release date, format is "NN Monthname, Year".
+
+=item Manufacturer()
+
+Music label, publishing company or manufacturer
+
+=item ImageUrlSmall()
+
+URL to a small (thumbnail) image of the item
+
+=item ImageUrlMedium()
+
+URL to a medium-size image of the item
+
+=item ImageUrlLarge()
+
+URL to a large image of the item
+
+=item ListPrice()
+
+List price of the item
+
+=item OurPrice()
+
+Amazon price of the item
+
+=item UsedPrice()
+
+Used price of the item
+
+=item SalesRank()
+
+Sales rank of the item (contains digits and commas, like 1,000,001)
+
+=item Media()
+
+Type of media (Paperback, etc.).
+
+=item NumMedia()
+
+Number of media the item carries (1,2 CDs etc.).
+
+=item ProductDescription()
+
+Lengthy textual description of the product.
+
+=item CollectiblePrice()
+
+Lowest price in "Collectible" category.
+
+=item CollectibleCount()
+
+Number of offerings in "Collectible" category.
+
+=item NumberOfOfferings()
+
+Total number of offerings in all categories.
+
+=item UsedCount()
+
+Number of offerings in "Used" category.
+
+=item ThirdPartyNewPrice()
+
+Lowest price in "Third Party New" category.
+
+=item ThirdPartyNewCount()
+
+Number of offerings in "Third Party New" category.
+
+=item year()
+
+The release year extracted from ReleaseDate().
+
+=item browse_nodes()
+
+Returns a list of browse nodes (text string categories) for this item.
+
+=item similar_asins()
+
+Returns a list of ASINs of similar items for this item.
+
+=back
+
+Please check the subclasses of C<Net::Amazon::Property> for specialized
+methods.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Property/Book.pm b/lib/Net/Amazon/Property/Book.pm
new file mode 100644
index 0000000..8a01756
--- /dev/null
+++ b/lib/Net/Amazon/Property/Book.pm
@@ -0,0 +1,152 @@
+######################################################################
+package Net::Amazon::Property::Book;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Property);
+
+__PACKAGE__->make_accessor($_) for qw(title publisher binding isbn);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+ bless $self, $class; # Bless into this class
+
+ if(exists $options{xmlref}) {
+ $self->init_via_xmlref($options{xmlref});
+ }
+
+ return $self;
+}
+
+##################################################
+sub init_via_xmlref {
+##################################################
+ my($self, $xmlref) = @_;
+
+ $self->SUPER::init_via_xmlref($xmlref);
+
+ $self->authors($xmlref->{Authors}->{Author});
+ $self->title($xmlref->{ProductName});
+ $self->publisher($xmlref->{Manufacturer});
+ $self->binding($xmlref->{Media});
+ $self->isbn($xmlref->{Isbn});
+}
+
+##################################################
+sub author {
+##################################################
+ my($self, $nameref) = @_;
+
+ # Only return the first author
+ return ($self->authors($nameref))[0];
+}
+
+##################################################
+sub authors {
+##################################################
+ my($self, $nameref) = @_;
+
+ if(defined $nameref) {
+ if(ref $nameref eq "ARRAY") {
+ $self->{authors} = $nameref;
+ } else {
+ $self->{authors} = [$nameref];
+ }
+ }
+
+ # Return a list
+ return $self->{authors} ? @{$self->{authors}} : ();
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return join('/', $self->authors) . ", " .
+ '"' . $self->title . '"' . ", " .
+ $self->year . ", " .
+ $self->OurPrice . ", " .
+ $self->Asin;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Property::Book - Class for books on amazon.com
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+
+ # ...
+
+ if($resp->is_success()) {
+ for my $prop ($resp->properties) {
+ print join("/", $prop->authors(), " ",
+ $prop->title(), " ",
+ $prop->publisher(), " ",
+ $prop->year(), "\n";
+ }
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Property::Book> is derived from
+C<Net::Amazon::Property> and on top of the all-purpose
+methods the base class provides, it offers specialized accessors for
+book parameters.
+
+=head2 METHODS
+
+=over 4
+
+=item authors()
+
+Returns a list of the book's authors. There's also a C<author()> method
+which just returns the I<first> author.
+
+=item publisher()
+
+Returns the book's publishing company as a string.
+
+=item title()
+
+Returns the book's title as a string.
+
+=item isbn()
+
+Returns the book's ISBN number.
+
+=item new(xmlref => $xmlref)
+
+Initializes an object by passing a hash of hashes structure containing
+the XML data returned from the service. Usually, this is just used by
+C<Net::Amazon> internally to initialize objects for on backcoming
+data.
+
+=back
+
+Check out L<Net::Amazon::Property> for all-purpose accessors, like
+C<year>, C<OurPrice>, C<ListPrice>, etc.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Property/DVD.pm b/lib/Net/Amazon/Property/DVD.pm
new file mode 100644
index 0000000..dc7fd5a
--- /dev/null
+++ b/lib/Net/Amazon/Property/DVD.pm
@@ -0,0 +1,156 @@
+######################################################################
+package Net::Amazon::Property::DVD;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Property);
+
+__PACKAGE__->make_accessor($_) for qw(title studio theatrical_release_date
+ media nummedia upc mpaa_rating);
+__PACKAGE__->make_array_accessor($_) for qw(directors starring features);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+ bless $self, $class; # Bless into this class
+
+ if(exists $options{xmlref}) {
+ $self->init_via_xmlref($options{xmlref});
+ }
+
+ return $self;
+}
+
+##################################################
+sub director {
+##################################################
+ my($self, $nameref) = @_;
+
+ # Only return the first director
+ return ($self->directors($nameref))[0];
+}
+
+##################################################
+sub init_via_xmlref {
+##################################################
+ my($self, $xmlref) = @_;
+
+ $self->SUPER::init_via_xmlref($xmlref);
+
+ $self->title($xmlref->{ProductName});
+ $self->studio($xmlref->{Manufacturer});
+ $self->directors($xmlref->{Directors}->{Director});
+ $self->starring($xmlref->{Starring}->{Actor});
+ $self->media($xmlref->{Media});
+ $self->nummedia($xmlref->{NumMedia});
+ $self->upc($xmlref->{Upc});
+ $self->theatrical_release_date($xmlref->{TheatricalReleaseDate});
+ $self->mpaa_rating($xmlref->{MpaaRating});
+ $self->features($xmlref->{Features}->{Feature});
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Property::DVD - Class for DVDs on amazon.com
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+
+ # ...
+
+ if($resp->is_success()) {
+ for my $prop ($resp->properties) {
+ print $_->title(), " ",
+ $_->studio(), " ",
+ $_->year(), "\n";
+ }
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Property::DVD> is derived from
+C<Net::Amazon::Property> and on top of the all-purpose
+methods the base class provides, it offers specialized accessors for
+DVD parameters.
+
+=head2 METHODS
+
+=over 4
+
+=item title()
+
+Returns the title of the DVD.
+
+=item studio()
+
+Returns the studio.
+
+=item directors()
+
+Returns a list of directors. Note that there's also a director() method
+only returning the first director.
+
+=item starring()
+
+Returns a list of actors starring in the movie.
+
+=item upc()
+
+Returns the DVD's UPC as a string.
+
+=item media()
+
+Returns the DVD's media type as a string.
+
+=item nummedia()
+
+Returns the DVD's number of media (number of discs) as a string.
+Amazon doesn't always send this back, so if you get undef assume it
+is 1.
+
+=item theatrical_release_date()
+
+Returns the DVD's theatrical release date.
+
+=item mpaa_rating()
+
+Returns the DVD's MPAA rating.
+
+=item features()
+
+Returns the DVD's features as a list of strings. Examples:
+"Color", "Closed-captioned", "Widescreen".
+
+=item new(xmlref => $xmlref)
+
+Initializes an object by passing a hash of hashes structure containing
+the XML data returned from the service. Usually, this is just used by
+C<Net::Amazon> internally to initialize objects for on backcoming
+data.
+
+=back
+
+Check out L<Net::Amazon::Property> for all-purpose accessors, like
+C<year>, C<OurPrice>, C<ListPrice>, etc.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Property/Music.pm b/lib/Net/Amazon/Property/Music.pm
new file mode 100644
index 0000000..59807be
--- /dev/null
+++ b/lib/Net/Amazon/Property/Music.pm
@@ -0,0 +1,161 @@
+######################################################################
+package Net::Amazon::Property::Music;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Property);
+
+__PACKAGE__->make_accessor($_) for qw(album label media nummedia upc);
+__PACKAGE__->make_array_accessor($_) for qw(artists tracks);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+ bless $self, $class; # Bless into this class
+
+ if(exists $options{xmlref}) {
+ $self->init_via_xmlref($options{xmlref});
+ }
+
+ return $self;
+}
+
+##################################################
+sub artist {
+##################################################
+ my($self, $nameref) = @_;
+
+ # Only return the first artist
+ return ($self->artists($nameref))[0];
+}
+
+##################################################
+sub init_via_xmlref {
+##################################################
+ my($self, $xmlref) = @_;
+
+ $self->SUPER::init_via_xmlref($xmlref);
+
+ $self->artists($xmlref->{Artists}->{Artist});
+ $self->tracks($xmlref->{Tracks}->{Track});
+ $self->album($xmlref->{ProductName});
+ $self->label($xmlref->{Manufacturer});
+ $self->upc($xmlref->{Upc});
+ $self->media($xmlref->{Media});
+ $self->nummedia($xmlref->{NumMedia});
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return join('/', $self->artists) . ", " .
+ '"' . $self->album . '"' . ", " .
+ $self->year . ", " .
+ $self->OurPrice . ", " .
+ $self->Asin;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Property::Music - Class for pop CDs on amazon.com
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+
+ # ...
+
+ if($resp->is_success()) {
+ for my $prop ($resp->properties) {
+ print join("/", $_->artists(), " ",
+ $_->album(), " ",
+ $_->label(), " ",
+ $_->year(), " ";
+ $_->upc(), " ";
+ $_->media(), " ";
+ $_->nummedia(), "\n";
+ }
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Property::Music> is derived from
+C<Net::Amazon::Property> and on top of the all-purpose
+methods the base class provides, it offers specialized accessors for
+popular music CD parameters.
+
+=head2 METHODS
+
+=over 4
+
+=item artists()
+
+Returns a list of the CD's artists. There's also a C<artist()> method
+which just returns the first artist.
+
+=item tracks()
+
+Returns a list of the CD's track titles.
+
+=item label()
+
+Returns the music label as a string.
+
+=item album()
+
+Returns the CD's title as a string.
+
+=item upc()
+
+Returns the CD's UPC as a string.
+
+=item media()
+
+Returns the CD's media type as a string.
+
+=item nummedia()
+
+Returns the CD's number of media (number of discs) as a string.
+Amazon doesn't always send this back, so if you get undef assume it
+is 1.
+
+=item new(xmlref => $xmlref)
+
+Initializes an object by passing a hash of hashes structure containing
+the XML data returned from the service. Usually, this is just used by
+C<Net::Amazon> internally to initialize objects for on backcoming
+data.
+
+=back
+
+Check out L<Net::Amazon::Property> for all-purpose accessors, like
+C<year>, C<OurPrice>, C<ListPrice>, etc.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 THANKS
+
+Thanks to Padraic Renaghan E<lt>padraic@renaghan.com<gt> for adding
+the upc/media/nummedia fields.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
diff --git a/lib/Net/Amazon/Request.pm b/lib/Net/Amazon/Request.pm
new file mode 100644
index 0000000..962d7bf
--- /dev/null
+++ b/lib/Net/Amazon/Request.pm
@@ -0,0 +1,221 @@
+######################################################################
+package Net::Amazon::Request;
+######################################################################
+
+use warnings;
+use strict;
+
+use constant DEFAULT_MODE => 'books';
+use constant DEFAULT_TYPE => 'heavy';
+use constant DEFAULT_PAGE_COUNT => 1;
+use constant DEFAULT_FORMAT => 'xml';
+use constant DEFAULT_SORT_CRITERIA => '+salesrank';
+
+use constant VALID_TYPES => { map { $_ => 1 } qw(heavy lite) };
+
+our $AMZN_XML_URL = "http://xml.amazon.com/onca/xml3";
+
+##################################################
+sub amzn_xml_url {
+##################################################
+ return $AMZN_XML_URL;
+}
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = {
+ mode => DEFAULT_MODE,
+ type => DEFAULT_TYPE,
+ page => DEFAULT_PAGE_COUNT,
+ f => DEFAULT_FORMAT,
+ sort => DEFAULT_SORT_CRITERIA,
+ %options,
+ };
+
+ die "Unknown type in ", __PACKAGE__, " constructor: ",
+ $self->{type} unless exists VALID_TYPES->{$self->{type}};
+
+ bless $self, $class;
+}
+
+##################################################
+sub params {
+##################################################
+ my($self) = @_;
+
+ return(%$self);
+}
+
+##################################################
+# Figure out the Response class to a given Request
+# class. To be used by sub classes.
+##################################################
+sub response_class {
+##################################################
+ my($self) = @_;
+
+ my $response_class = ref($self);
+ $response_class =~ s/Request/Response/;
+ return $response_class;
+}
+
+##
+## 'PRIVATE' METHODS
+##
+
+# CLASS->_convert_option( OPTIONS, ORIGINAL, TARGET [, CALLBACK] )
+#
+# Takes a reference to a hash of OPTIONS and renames the
+# ORIGINAL key name to the TARGET key name. If the optional
+# CALLBACK subroutine reference is defined, that subroutine
+# is invoked with two arguments:
+#
+# CALLBACK->( OPTIONS, TARGET )
+#
+# The result of the CALLBACK's execution is then returned to
+# the caller. No assumptions are made about what the CALLBACK
+# should return (or even *if* is should return)--that's the
+# caller's responsibility.
+#
+# Returns 1 in the absensence of a CALLBACK.
+#
+sub _convert_option {
+ my ($class, $options, $original, $target, $callback) = @_;
+
+ if ( exists $options->{$original} ) {
+ $options->{$target} = $options->{$original};
+ delete $options->{$original};
+ }
+
+ return 1 unless ( $callback );
+
+ # The key name is explicitly passed-in so that the caller doesn't
+ # have think "Hrmm.. now which key am I working on, the original
+ # or the target key?" Confusion is bad.
+ return $callback->($options, $target);
+}
+
+# CLASS->_assert_options_defined( OPTIONS, KEYS )
+#
+# Takes a reference to a hash of OPTIONS and a list of
+# one or more KEYS. Tests to see if each key in KEYS
+# has a defined value. Calls die() upon the first
+# missing key. Otherwise, returns undef.
+#
+sub _assert_options_defined {
+ my ($class, $options, @keys) = @_;
+
+ foreach my $key ( @keys ) {
+ die "Mandatory parameter '$key' not defined"
+ unless ( defined $options->{$key} );
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request - Baseclass for requests to Amazon's web service
+
+=head1 SYNOPSIS
+
+ my $req = Net::Amazon::Request::XXX->new(
+ [ type => 'heavy', ]
+ [ page => $start_page, ]
+ [ mode => $mode, ]
+ [ offer => 'All', ]
+ [ sort => $sort_type, ]
+ );
+
+=head1 DESCRIPTION
+
+Don't use this class directly, use derived classes
+(like C<Net::Amazon::Request::ASIN>, C<Net::Amazon::Request::Wishlist>
+etc.) instead to specify the type of request and its parameters.
+
+However, there's a bunch of parameters to the constructor
+that all request types have in common, here they are:
+
+=over 4
+
+=item type
+
+Defaults to C<heavy>, but can be set to C<lite> if no reviews etc.
+on a product are wanted. Some fields (e.g. C<isbn>) are not going to be
+available in C<lite> mode, though.
+
+=item mode
+
+Defaults to C<books>, but can be set to other catalog values.
+
+=item page
+
+Defaults to C<1>, but can be set to a different number to
+start with a different result page. Used in conjunction with the
+C<max_pages> parameter of the C<Net::Amazon> object. C<page> is the
+offset, C<max_pages> is the maximum number of pages pulled in starting
+at C<page>.
+
+=item sort
+
+Defaults to C<+salesrank>, but search results can be sorted in various
+ways, depending on the type of product returned by the search. Search
+results may be sorted by the following criteria:
+
+=over 8
+
+=item *
+Featured Items
+
+=item *
+Bestselling
+
+=item *
+Alphabetical (A-Z and Z-A)
+
+=item *
+Price (High to Low and Low to High)
+
+=item *
+Publication or Release Date
+
+=item *
+Manufacturer
+
+=item *
+Average Customer Review
+
+=item *
+Artist Name
+
+=back
+
+Consult L<Net::Amazon::Request::Sort> for details.
+
+=item offer
+
+To receive values for the fields
+C<CollectibleCount>, C<NumberOfOfferings>, C<UsedCount>,
+specify C<offer =E<gt> "All">.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/ASIN.pm b/lib/Net/Amazon/Request/ASIN.pm
new file mode 100644
index 0000000..4d8f752
--- /dev/null
+++ b/lib/Net/Amazon/Request/ASIN.pm
@@ -0,0 +1,139 @@
+######################################################################
+package Net::Amazon::Request::ASIN;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+# These values are defined in the AWS SDK
+# (http://amazon.com/webservices) under
+# "Product and Catalog Data" / "ASIN and ISBN Searches"
+use constant MAX_ASINS_PER_TYPE => {
+ heavy => 10,
+ lite => 30,
+};
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options, 'asin');
+
+ $class->_convert_option(\%options,
+ 'asin',
+ 'AsinSearch',
+ \&_process_asin_option);
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##
+## PRIVATE FUNCTIONS
+##
+
+# _process_asin_option( OPTIONS, KEY )
+#
+# Takes a reference to a hash of OPTIONS and checks the value keyed by
+# KEY to make sure it looks legitimate. If the value associated with
+# KEY is an array, we check to make sure that we're not asking for
+# too many asins at once.
+#
+# Returns true if all goes well. If any problems are encountered,
+# die() will be called.
+#
+sub _process_asin_option {
+ my ($options, $key) = @_;
+
+ # If the asins are supplied in the form of an array, we have to
+ # make sure that the caller isn't trying to ask for too many at a
+ # time. If we don't make this test, those excessive asins will be
+ # silently ignored by the AWS servers...resulting in potentially
+ # confusing results for the user.
+ if ( ref $options->{$key} eq 'ARRAY' ) {
+ my $type = $options->{'type'} || __PACKAGE__->SUPER::DEFAULT_TYPE;
+ my $max_asins = MAX_ASINS_PER_TYPE->{$type};
+
+ # Dying is the right thing to do here because this is
+ # indicative of a programming error.
+ die "Only $max_asins may be requested at a time using type '$type'"
+ if ( @{$options->{$key}} > $max_asins );
+
+ $options->{$key} = join ',', @{$options->{$key}};
+ } elsif ( ref $options->{$key} ) {
+ die "The 'asin' parameter must either be a scalar or an array";
+ }
+
+ return 1;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::ASIN - Class for submitting ASIN requests
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::ASIN;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::ASIN->new(
+ asin => '0201360683'
+ );
+
+ # Response is of type Net::Amazon::Response::ASIN
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::ASIN> is a class used to submit ASIN requests
+to the Amazon web service.
+
+The ASIN of the item to look is specified in the C<asin> parameter.
+
+Upon success, the responses' C<properties()> method will return one
+single C<Net::Amazon::Property::*> object.
+
+=head2 METHODS
+
+=over 4
+
+=item new( asin => $asin )
+
+Constructs a new C<Net::Amazon::Request::ASIN> object, used to query
+the Amazon web service for an item with the specified ASIN number.
+
+C<$asin> can also be a reference to an array of ASINs, like in
+
+ $ua->search(asin => ["0201360683", "0596005083"])
+
+in which case a search for multiple ASINs is performed, returning a list of
+results.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Artist.pm b/lib/Net/Amazon/Request/Artist.pm
new file mode 100644
index 0000000..4c111f8
--- /dev/null
+++ b/lib/Net/Amazon/Request/Artist.pm
@@ -0,0 +1,86 @@
+######################################################################
+package Net::Amazon::Request::Artist;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ if(exists $options{artist}) {
+ $options{ArtistSearch} = $options{artist};
+ delete $options{artist};
+ $options{mode} = "music";
+ } else {
+ die "Mandatory parameter 'artist' not defined";
+ }
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Artist - Class for submitting Artist requests
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Artist;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Artist->new(
+ artist => 'Zwan'
+ );
+
+ # Response is of type Net::Amazon::Response::Artist
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Artist> is a class used to submit Artist search
+requests to the Amazon web service.
+
+The artist to search for is specified in the C<artist> parameter.
+
+Upon success, the responses' C<properties()> method will return a list of
+C<Net::Amazon::Property::Music> objects.
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head2 METHODS
+
+=over 4
+
+=item new( artist => $artist )
+
+Constructs a new C<Net::Amazon::Request::Artist> object, used to query
+the Amazon web service for items of a given artist.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Blended.pm b/lib/Net/Amazon/Request/Blended.pm
new file mode 100644
index 0000000..1000eec
--- /dev/null
+++ b/lib/Net/Amazon/Request/Blended.pm
@@ -0,0 +1,80 @@
+######################################################################
+package Net::Amazon::Request::Blended;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options, 'blended');
+
+ $class->_convert_option(\%options,
+ 'blended',
+ 'BlendedSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Blended - request class for 'Blended Search'
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Blended;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Blended->new(
+ blended => 'perl'
+ );
+
+ # Response is of type Net::Amazon::Response::Blended
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Blended> is a class used to request
+I<Blended Searches> from the Amazon web service.
+
+The C<blended> parameter specifies the keyword search string
+for the blended query. C<mode> is not applicable to blended
+searches which returns books, music, etc all at once.
+
+Upon success, the response's C<properties()> method will return a list
+of C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new(keyword => $search_string)
+
+Constructs a new C<Net::Amazon::Request::Blended> object.
+
+See the "Amazon Web Services 2.1 API and Integration Guide" for details.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHORS
+
+Robert Graff, E<lt>rgraff@workingdemo.comE<gt>
+
+=cut
diff --git a/lib/Net/Amazon/Request/BrowseNode.pm b/lib/Net/Amazon/Request/BrowseNode.pm
new file mode 100644
index 0000000..2f8d92f
--- /dev/null
+++ b/lib/Net/Amazon/Request/BrowseNode.pm
@@ -0,0 +1,137 @@
+######################################################################
+package Net::Amazon::Request::BrowseNode;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options,
+ qw(browsenode mode));
+
+ $class->_convert_option(\%options,
+ 'browsenode',
+ 'BrowseNodeSearch',
+ \&_assert_node_is_numeric);
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##
+## 'PRIVATE' FUNCTIONS
+##
+
+# _assert_node_is_numeric( OPTIONS, KEY )
+#
+# Takes a reference to a hash of OPTIONS and makes sure
+# that the browse node id keyed by KEY is numeric.
+#
+# Returns if all is well, dies otherwise.
+#
+sub _assert_node_is_numeric {
+ my ($options, $key) = @_;
+
+ die "Browse Node ID must be numeric."
+ if ( $options->{$key} =~ /\D/ );
+}
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::BrowseNode - request class for browse node search
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::BrowseNode;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::BrowseNode->new(
+ browsenode => 30,
+ mode => 'books'
+ );
+
+ # Response is of type Net::Amazon::Response::BrowseNode
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::BrowseNode> is a class used to submit node search
+requests to the Amazon web service.
+
+The node to search for is specified in the C<browsenode> parameter. The
+browse node ID is a number that corresponds to a general subject area
+of Amazon.com.
+
+To find browse node IDs, the best way is to visit the "browse" area
+of the various product lines at Amazon.com. When you find a subject area
+that you would like to generate XML for, look at the web page URL. The
+browse ID should appear after the string "/tg/browse/-/". Here are some
+examples of URLs that contain browse IDs:
+
+=over 8
+
+http://www.amazon.com/exec/obidos/tg/browse/-/30
+(In this example, the browse ID = 30)
+
+http://www.amazon.com/exec/obidos/tg/browse/-/467970
+(In this example, the browse ID = 467970)
+
+http://www.amazon.com/exec/obidos/tg/browse/-/602314
+(In this example, the browse ID = 60231
+
+=back
+
+Please be aware that some nodes cannot be used with a
+BrowseNodeSearch. (The vast majority of them can, but you
+may run across a few that simply will not work). It is also
+important to point out that from time to time, some browse
+nodes are deprecated or are changed without notice.
+
+The catalog to search in is specified in the C<mode> parameter,
+typical values are C<books>, C<music>, C<classical> or C<electronics>.
+
+An optional C<keywords> parameter may be added to filter the results by that keyword.
+
+Upon success, the responses' C<properties()> method will return a list of
+C<Net::Amazon::Properties::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new( browsenode => $nodeID, mode => $mode [, keywords => $keywords] )
+
+Constructs a new C<Net::Amazon::Request::BrowseNode> object, used to query
+the Amazon web service for items in a particular category (node) in the
+mode (catalog) specified.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 AUTHOR
+
+Net::Amazon framework by Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+BrowseNode.pm by Jackie Hamilton, E<lt>kira@cgi101.comE<gt>
+
+=head1 LICENSE
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Exchange.pm b/lib/Net/Amazon/Request/Exchange.pm
new file mode 100644
index 0000000..df75549
--- /dev/null
+++ b/lib/Net/Amazon/Request/Exchange.pm
@@ -0,0 +1,91 @@
+######################################################################
+package Net::Amazon::Request::Exchange;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ if(exists $options{exchange}) {
+ $options{ExchangeSearch} = $options{exchange};
+ delete $options{exchange};
+ $options{type} = "lite";
+ $options{mode} = "";
+ } else {
+ die "Mandatory parameter 'exchange' not defined";
+ }
+
+# if(!exists $options{exchange}) {
+# die "Mandatory parameter 'exchange' not defined";
+# }
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Exchange - Class for submitting Exchange requests
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Exchange;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Exchange->new(
+ exchange => 'Y04Y3424291Y2398445'
+ );
+
+ # Response is of type Net::Amazon::Response::Seller
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Exchange> is a class used to submit Exchange search
+requests to the Amazon web service. Exchange requests send an item's
+exchange ID and retrieve a description of the item, offered by a third
+party seller on Amazon.
+
+Upon success, the responses' C<result()> method will return a single
+C<Net::Amazon::Result::Seller::Listing> object.
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head2 METHODS
+
+=over 4
+
+=item new( exchange => $exchange_id )
+
+Constructs a new C<Net::Amazon::Request::Exchange> object, used to query
+the Amazon web service with the given seller id.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2005 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Keyword.pm b/lib/Net/Amazon/Request/Keyword.pm
new file mode 100644
index 0000000..0b15d1d
--- /dev/null
+++ b/lib/Net/Amazon/Request/Keyword.pm
@@ -0,0 +1,90 @@
+######################################################################
+package Net::Amazon::Request::Keyword;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options,
+ qw(keyword mode));
+
+ $class->_convert_option(\%options,
+ 'keyword',
+ 'KeywordSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Keyword - request class for keyword search
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Keyword;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Keyword->new(
+ keyword => 'Zwan',
+ mode => 'books'
+ );
+
+ # Response is of type Net::Amazon::Response::Keyword
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Keyword> is a class used to submit keyword search
+requests to the Amazon web service.
+
+The keyword to search for is specified in the C<keyword> parameter.
+
+The catalog to search in is specified in the C<mode> parameter,
+typical values are C<books>, C<music>, C<classical> or C<electronics>.
+
+Upon success, the responses' C<properties()> method will return a list of
+C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new( keyword => $keyword, mode => $mode )
+
+Constructs a new C<Net::Amazon::Request::Keyword> object, used to query
+the Amazon web service for items matching a given keyword in the
+mode (catalog) specified.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Manufacturer.pm b/lib/Net/Amazon/Request/Manufacturer.pm
new file mode 100644
index 0000000..0e8adb8
--- /dev/null
+++ b/lib/Net/Amazon/Request/Manufacturer.pm
@@ -0,0 +1,78 @@
+######################################
+package Net::Amazon::Request::Manufacturer;
+######################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+######################################
+sub new {
+######################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options,
+ 'manufacturer');
+
+ $class->_convert_option(\%options,
+ 'manufacturer',
+ 'ManufacturerSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Manufacturer - Class for submitting Manufacturer requests
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Manufacturer;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Manufacturer->new(
+ manufacturer => 'Disney'
+ );
+
+ # Response is of type Net::Amazon::Response::Manufacturer
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Manufacturer> is a class used to submit
+searches for items made by a given manufacturer.
+
+The manufacturer to search for is specified in the C<manufacturer> parameter.
+
+Upon success, the responses' C<properties()> method will return one
+or more C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new( manufacturer => $manufacturer )
+
+Constructs a new C<Net::Amazon::Request::Manufacturer> object, used to query
+the Amazon web service for an item with the specified manufacturer name.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHORS
+
+Bill Fitzpatrick
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=cut
diff --git a/lib/Net/Amazon/Request/Power.pm b/lib/Net/Amazon/Request/Power.pm
new file mode 100644
index 0000000..fdfd74e
--- /dev/null
+++ b/lib/Net/Amazon/Request/Power.pm
@@ -0,0 +1,95 @@
+######################################################################
+package Net::Amazon::Request::Power;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options,
+ qw(power mode));
+
+ $class->_convert_option(\%options,
+ 'power',
+ 'PowerSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Power - request class for 'Power Search'
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Power;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Power->new(
+ power => 'subject: perl and author: schwartz',
+ mode => 'books',
+ );
+
+ # Response is of type Net::Amazon::Response::Power
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Power> is a class used to request
+so-called I<Power Searches> from the Amazon web service.
+
+The C<power> parameter specifies the power search string, C<mode>
+defines which properties to look for.
+
+Upon success, the response's C<properties()> method will return a list
+of C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new(power => $search_string, mode => $property)
+
+Constructs a new C<Net::Amazon::Request::Power> object. C<$property>
+is typically C<"books">. Examples for C<$search_string> are:
+
+ author: schwartz
+
+ author: schwartz and pubdate: after 10-2002
+
+ subject: perl and (objects or object-oriented)
+
+ keywords: "high tech*" and not fiction and pubdate: during 1999
+
+ power "author: randal schwartz and publisher: Addison Wesley"
+
+ author: randal schwartz and title: object books
+
+See the "Amazon Web Services 2.1 API and Integration Guide" for details.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHORS
+
+Martin Streicher, E<lt>martin.streicher@apress.comE<gt>
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=cut
diff --git a/lib/Net/Amazon/Request/Seller.pm b/lib/Net/Amazon/Request/Seller.pm
new file mode 100644
index 0000000..54e1930
--- /dev/null
+++ b/lib/Net/Amazon/Request/Seller.pm
@@ -0,0 +1,84 @@
+######################################################################
+package Net::Amazon::Request::Seller;
+######################################################################
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ if(exists $options{seller}) {
+ $options{SellerSearch} = $options{seller};
+ delete $options{seller};
+ } else {
+ die "Mandatory parameter 'seller' not defined";
+ }
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Seller - Class for submitting Seller requests
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Seller;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Seller->new(
+ seller => 'A2GXAGU54VOP7'
+ );
+
+ # Response is of type Net::Amazon::Response::Seller
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Seller> is a class used to submit Seller search
+requests to the Amazon web service.
+
+The seller to search for is specified in the C<seller> parameter, which
+contains the seller's ID (not the seller's nickname!).
+
+Upon success, the responses' C<result()> method will return a single
+C<Net::Amazon::Result::Seller> object.
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head2 METHODS
+
+=over 4
+
+=item new( seller => $seller_id )
+
+Constructs a new C<Net::Amazon::Request::Seller> object, used to query
+the Amazon web service with the given seller id.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2004 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Similar.pm b/lib/Net/Amazon/Request/Similar.pm
new file mode 100644
index 0000000..c5b5a53
--- /dev/null
+++ b/lib/Net/Amazon/Request/Similar.pm
@@ -0,0 +1,95 @@
+######################################################################
+package Net::Amazon::Request::Similar;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+our $AMZN_XML_URL = "http://xml.amazon.com/onca/xml3";
+
+##################################################
+sub amzn_xml_url {
+##################################################
+ return $AMZN_XML_URL;
+}
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ # For backwards compatibility
+ $class->_convert_option(\%options, 'asin', 'similar');
+
+ $class->_assert_options_defined(\%options, 'similar');
+
+ $class->_convert_option(\%options,
+ 'similar',
+ 'SimilaritySearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Similar - request class for 'Similarities Search'
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Similar;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Similar->new(
+ similar => 'B00005B6TL',
+ );
+
+ # Response is of type Net::Amazon::Response::Similar
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Similar> is a class used to request
+so-called I<Similarities Searches> from the Amazon web service.
+
+The C<asin> parameter specifies the ASIN of the item which you want
+to get similar items for.
+
+Upon success, the response's C<properties()> method will return a list
+of C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new(similar => $asin)
+
+Constructs a new C<Net::Amazon::Request::Similar> object.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Sort.pm b/lib/Net/Amazon/Request/Sort.pm
new file mode 100644
index 0000000..059845d
--- /dev/null
+++ b/lib/Net/Amazon/Request/Sort.pm
@@ -0,0 +1,246 @@
+=pod
+
+=head1 SORT TYPES
+
+Search results can be sorted in various ways, depending on the type of
+product returned by the search. If a sort parameter isn't specified in
+the request, the results will be ordered as if the +salesrank value is
+specified.
+
+=head2 Sorting Books Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Average Customer Review | +reviewrank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +pricerank |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | +inverse-pricerank |
+ |-------------------------+-------------------------+
+ | Publication Date | +daterank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ +---------------------------------------------------+
+
+=head2 Sorting Software Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical | +titlerank |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | +price |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | -price |
+ +---------------------------------------------------+
+
+=head2 Sorting Outdoor Living Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +psrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ |-------------------------+-------------------------+
+ | Manufacturer (A-Z) | +manufactrank |
+ |-------------------------+-------------------------+
+ | Manufacturer (Z-A) | -manufactrank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +price |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | -price |
+ +---------------------------------------------------+
+
+=head2 Sorting Tools Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +psrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ |-------------------------+-------------------------+
+ | Manufacturer (A-Z) | +manufactrank |
+ |-------------------------+-------------------------+
+ | Manufacturer (Z-A) | -manufactrank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +price |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | -price |
+ +---------------------------------------------------+
+
+=head2 Sorting Camera and Photo Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ +---------------------------------------------------+
+
+=head2 Sorting Computers Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +psrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ +---------------------------------------------------+
+
+=head2 Sorting Video Games Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical | +titlerank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +price |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | -price |
+ +---------------------------------------------------+
+
+=head2 Sorting Music Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +psrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Artist Name | +artistrank |
+ |-------------------------+-------------------------+
+ | Original Release Date | +orig-rel-date |
+ |-------------------------+-------------------------+
+ | Alphabetical | +titlerank |
+ +---------------------------------------------------+
+
+=head2 Sorting Office Products Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +price |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | -price |
+ |-------------------------+-------------------------+
+ | Review | +reviewrank |
+ +---------------------------------------------------+
+
+=head2 Sorting Video Results
+
+ +---------------------------------------------------+
+ | Sort Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +psrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical | +titlerank |
+ +---------------------------------------------------+
+
+=head2 Sorting Electronics Results
+
+ +---------------------------------------------------+
+ | Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical | +titlerank |
+ |-------------------------+-------------------------+
+ | Review | +reviewrank |
+ +---------------------------------------------------+
+
+=head2 Sorting DVDs Results
+
+ +---------------------------------------------------+
+ | Type | Value |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical | +titlerank |
+ +---------------------------------------------------+
+
+=head2 Sorting Kitchen Results
+
+ +---------------------------------------------------+
+ | Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (Z-A) | -titlerank |
+ |-------------------------+-------------------------+
+ | Manufacturer (A-Z) | +manufactrank |
+ |-------------------------+-------------------------+
+ | Manufacturer (Z-A) | -manufactrank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +price |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | -price |
+ +---------------------------------------------------+
+
+=head2 Sorting Toys Results
+
+ +---------------------------------------------------+
+ | Type | Value |
+ |-------------------------+-------------------------+
+ | Featured Items | +pmrank |
+ |-------------------------+-------------------------+
+ | Bestselling | +salesrank |
+ |-------------------------+-------------------------+
+ | Price (Low to High) | +pricerank |
+ |-------------------------+-------------------------+
+ | Price (High to Low) | +inverse-pricerank |
+ |-------------------------+-------------------------+
+ | Alphabetical (A-Z) | +titlerank |
+ +---------------------------------------------------+
+
+=cut
diff --git a/lib/Net/Amazon/Request/TextStream.pm b/lib/Net/Amazon/Request/TextStream.pm
new file mode 100644
index 0000000..62a0717
--- /dev/null
+++ b/lib/Net/Amazon/Request/TextStream.pm
@@ -0,0 +1,76 @@
+######################################################################
+package Net::Amazon::Request::TextStream;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options,
+ 'textstream');
+
+ $class->_convert_option(\%options,
+ 'textstream',
+ 'TextStreamSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::TextStream - request class for text stream search
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::TextStream;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::TextStream->new(
+ textstream => 'Here is some text that mentions the Rolling Stones.',
+ );
+
+ # Response is of type Net::Amazon::Response::TextStream
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::TextStream> is a class used to perform a search on
+a block of text. Amazon extracts keywords from the given block of text,
+but note that conjunctions and helper words, such as "and", "or", "the",
+etc. are not excluded, so strip them out yourself if need be.
+
+TextStream searching is only available for the US service.
+
+Upon success, the response's C<properties()> method will return a list
+of C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new(textstream => $text)
+
+Constructs a new C<Net::Amazon::Request::TextStream> object, used to query
+the Amazon web service with a block of text.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=cut
diff --git a/lib/Net/Amazon/Request/UPC.pm b/lib/Net/Amazon/Request/UPC.pm
new file mode 100644
index 0000000..ae77645
--- /dev/null
+++ b/lib/Net/Amazon/Request/UPC.pm
@@ -0,0 +1,94 @@
+######################################################################
+package Net::Amazon::Request::UPC;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ $class->_assert_options_defined(\%options, 'upc');
+
+ $class->_convert_option(\%options,
+ 'upc',
+ 'UpcSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::UPC - request class for UPC search
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::UPC;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::UPC->new(
+ upc => '724381198421',
+ mode => 'music',
+
+ );
+
+ # Response is of type Net::Amazon::Response::UPC
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::UPC> is a class used to submit UPC (product barcode)
+search requests to the Amazon web service.
+
+The UPC number to search for is specified in the C<upc> parameter.
+It currently works with the following values of the C<mode> parameter:
+C<music>,
+C<classical>,
+C<software>,
+C<dvd>,
+C<video>,
+C<vhs>,
+C<electronics>,
+C<pc-hardware>, and
+C<photo>.
+
+Upon success, the response's C<properties()> method will return a single
+C<Net::Amazon::Property::Music> object.
+
+=head2 METHODS
+
+=over 4
+
+=item new(upc => $upc)
+
+Constructs a new C<Net::Amazon::Request::UPC> object, used to query
+the Amazon web service for an item with the given UPC number.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Request/Wishlist.pm b/lib/Net/Amazon/Request/Wishlist.pm
new file mode 100644
index 0000000..824d5d4
--- /dev/null
+++ b/lib/Net/Amazon/Request/Wishlist.pm
@@ -0,0 +1,89 @@
+######################################################################
+package Net::Amazon::Request::Wishlist;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Request);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ # For backwards compatibility:
+ $class->_convert_option(\%options, 'id', 'wishlist');
+
+ $class->_assert_options_defined(\%options, 'wishlist');
+
+ $class->_convert_option(\%options,
+ 'wishlist',
+ 'WishlistSearch');
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Request::Wishlist - request class for wishlist search
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+ use Net::Amazon::Request::Wishlist;
+
+ my $ua = Net::Amazon->new(
+ token => 'YOUR_AMZN_TOKEN'
+ );
+
+ my $req = Net::Amazon::Request::Wishlist->new(
+ wishlist => '1XL5DWOUFMFVJ',
+ );
+
+ # Response is of type Net::Amazon::Response::Wishlist
+ my $resp = $ua->request($req);
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Request::Wishlist> is a class used to request
+a specified wishlist.
+
+The wishlist ID (can be found as parameters in URLs when a customer's
+Amazon wishlist is being pulled up) is specified in the C<id> parameter.
+
+Upon success, the response's C<properties()> method will return a list
+of C<Net::Amazon::Property::*> objects.
+
+=head2 METHODS
+
+=over 4
+
+=item new(wishlist => $id)
+
+Constructs a new C<Net::Amazon::Request::Wishlist> object, used to query
+the Amazon web service for a specific wishlist, identified by the wishlist
+ID.
+
+=back
+
+Check L<Net::Amazon::Request> for common request parameters not listed here.
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Response.pm b/lib/Net/Amazon/Response.pm
new file mode 100644
index 0000000..6147e0e
--- /dev/null
+++ b/lib/Net/Amazon/Response.pm
@@ -0,0 +1,214 @@
+######################################################################
+package Net::Amazon::Response;
+######################################################################
+use warnings;
+use strict;
+
+use base qw(Net::Amazon);
+
+use Text::Wrap qw($columns wrap);
+use XML::Simple;
+
+our @FORCE_ARRAY_FIELDS = ();
+
+__PACKAGE__->make_accessor($_) for qw(
+ status messages items xmlref total_results);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = {
+ status => "",
+ messages => [],
+ items => [],
+ xmlref => {},
+ total_results => undef,
+ };
+
+ bless $self, $class;
+}
+
+sub message {
+ my($self) = @_;
+
+ return join(";",@{$self->{messages}});
+}
+
+###########################################
+sub is_success {
+###########################################
+ my($self) = @_;
+
+ return $self->{status} ? 1 : "";
+}
+
+###########################################
+sub is_error {
+###########################################
+ my($self) = @_;
+
+ return !$self->is_success();
+}
+
+###########################################
+sub push_item {
+###########################################
+ my($self, $item) = @_;
+
+ push @{$self->{items}}, $item;
+}
+
+###########################################
+sub as_string {
+###########################################
+ my($self) = @_;
+
+ return Data::Dumper::Dumper($self);
+}
+
+###########################################
+sub list_as_string {
+###########################################
+ my($self, @properties) = @_;
+
+ my $full = "";
+
+ # Column with
+ $columns = 60;
+ my $bullet = 1;
+
+ foreach my $property (@properties) {
+ $full .= "\n" if $full;
+ my $bullet_string = sprintf("[%d]%s",
+ $bullet, (" " x (3-length($bullet))));
+ $full .= wrap("", " ", $bullet_string . $property->as_string());
+ $bullet++;
+ }
+
+ return $full;
+}
+
+##################################################
+sub properties {
+##################################################
+ my($self) = @_;
+
+ my @properties = ();
+
+ if($self->is_success && ref($self->{xmlref}->{Details}) eq 'ARRAY') {
+ foreach my $xmlref (@{$self->{xmlref}->{Details}}) {
+ my $property = Net::Amazon::Property::factory(xmlref => $xmlref);
+ push @properties, $property;
+ }
+ }
+
+ if(wantarray) {
+ return (@properties);
+ }
+
+ if(@properties) {
+ # Scalar context and we've got results. Return the first one.
+ return $properties[0];
+ }
+
+ # Scalar context and we don't have anything.
+ return undef;
+}
+
+##################################################
+sub xml_parse {
+##################################################
+ my($self, $xml) = @_;
+
+ my $xs = XML::Simple->new();
+ return $xs->XMLin($xml, ForceArray => [ @FORCE_ARRAY_FIELDS ]);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Response - Baseclass for responses from Amazon's web service
+
+=head1 SYNOPSIS
+
+ $resp = $ua->request($request);
+
+ if($resp->is_success()) {
+ print $resp->as_string();
+ }
+
+ if($resp->is_error()) {
+ print $resp->message();
+ }
+
+ if($resp->is_success()) {
+ for my $property ($resp->properties) {
+ print $property->as_string(), "\n";
+ }
+ }
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Response> is the baseclass for responses coming back
+from the useragent's C<request> method. Responses are typically
+not of type C<Net::Amazon::Response> but one of its subclasses
+C<Net::Amazon::Response::*>. However, for basic error handling and
+dumping content, C<Net::Amazon::Response>'s methods are typically used,
+because we typically don't know what type of object we're
+actually dealing with.
+
+=head2 METHODS
+
+=over 4
+
+=item is_success()
+
+Returns true if the request was successful. This doesn't mean any objects
+have been found, it just indicates a successful roundtrip.
+
+=item is_error()
+
+Returns true if an error occurred. Use C<message()> to determine what
+kind of error.
+
+=item properties()
+
+Returns the list of C<Net::Amazon::Property> objects which were found
+by the query.
+
+=item as_string()
+
+Dumps the content of the response.
+
+=item message()
+
+Returns the error message as a string in case an error occurred. In case
+several errors occurred, they're stringed together. Look up C<messages()>
+if you need them separated.
+
+=item messages()
+
+Returns all error messages for a response as a reference to an array
+of string messages.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Response/ASIN.pm b/lib/Net/Amazon/Response/ASIN.pm
new file mode 100644
index 0000000..32bad76
--- /dev/null
+++ b/lib/Net/Amazon/Response/ASIN.pm
@@ -0,0 +1,28 @@
+######################################################################
+package Net::Amazon::Response::ASIN;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Artist.pm b/lib/Net/Amazon/Response/Artist.pm
new file mode 100644
index 0000000..0ee653b
--- /dev/null
+++ b/lib/Net/Amazon/Response/Artist.pm
@@ -0,0 +1,29 @@
+######################################################################
+package Net::Amazon::Response::Artist;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use Data::Dumper;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Blended.pm b/lib/Net/Amazon/Response/Blended.pm
new file mode 100644
index 0000000..3c75ded
--- /dev/null
+++ b/lib/Net/Amazon/Response/Blended.pm
@@ -0,0 +1,73 @@
+######################################################################
+package Net::Amazon::Response::Blended;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use XML::Simple;
+
+our @FORCE_ARRAY_FIELDS = qw(ProductLine);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+##################################################
+sub xmlref_add {
+##################################################
+ my($self, $xmlref) = @_;
+
+ my $nof_items_added = 0;
+
+ unless(ref($self->{xmlref}) eq "HASH" &&
+ ref($self->{xmlref}->{Details}) eq "ARRAY") {
+ $self->{xmlref}->{Details} = [];
+ }
+
+ if ($xmlref->{ProductLine} && (ref($xmlref->{ProductLine}) eq "ARRAY")) {
+ my @lines = @{$xmlref->{ProductLine}}; # Copy the lines
+ # sort the copies by relevance
+ @lines = sort { $a->{RelevanceRank} <=> $b->{RelevanceRank} } @lines;
+
+ foreach (@lines) {
+ next unless $_->{ProductInfo}->{Details};
+ my $details = $_->{ProductInfo}->{Details};
+ if (ref($details) eq "ARRAY") {
+ push @{$self->{xmlref}->{Details}}, @$details;
+ $nof_items_added += scalar @$details;
+ } else {
+ push @{$self->{xmlref}->{Details}}, $details;
+ $nof_items_added++;
+ }
+ }
+ }
+
+ return $nof_items_added;
+}
+
+##################################################
+sub xml_parse {
+##################################################
+ my($self, $xml) = @_;
+
+ my $xs = XML::Simple->new();
+ return $xs->XMLin($xml, ForceArray => [ @FORCE_ARRAY_FIELDS ]);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/BrowseNode.pm b/lib/Net/Amazon/Response/BrowseNode.pm
new file mode 100644
index 0000000..8f40a63
--- /dev/null
+++ b/lib/Net/Amazon/Response/BrowseNode.pm
@@ -0,0 +1,29 @@
+######################################################################
+package Net::Amazon::Response::BrowseNode;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use Data::Dumper;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Exchange.pm b/lib/Net/Amazon/Response/Exchange.pm
new file mode 100644
index 0000000..56852fe
--- /dev/null
+++ b/lib/Net/Amazon/Response/Exchange.pm
@@ -0,0 +1,81 @@
+######################################################################
+package Net::Amazon::Response::Exchange;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use Net::Amazon::Result::Seller::Listing;
+use Log::Log4perl qw(:easy);
+
+__PACKAGE__->make_array_accessor($_) for qw(listings);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub result {
+##################################################
+ my($self) = @_;
+
+ if($self->is_success()) {
+ return Net::Amazon::Result::Seller::Listing->new(
+ xmlref => $self->{xmlref}->{ListingProductDetails}->[0],
+ );
+ }
+
+ return undef;
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return "TODO: as_string not defined yet in ", __PACKAGE__;
+}
+
+##################################################
+sub xmlref_add {
+##################################################
+ my($self, $xmlref) = @_;
+
+ my $nof_items_added = 0;
+
+ unless(ref($self->{xmlref}) eq "HASH" &&
+ ref($self->{xmlref}->{ListingProductDetails}) eq "ARRAY") {
+ $self->{xmlref}->{Details} = [];
+ }
+
+ if(ref($xmlref->{ListingProductDetails}) eq "ARRAY") {
+ # Is it an array of items?
+ push @{$self->{xmlref}->{ListingProductDetails}},
+ @{$xmlref->{ListingProductDetails}};
+ $nof_items_added = scalar @{$xmlref->{ListingProductDetails}};
+ } else {
+ # It is a single item
+ push @{$self->{xmlref}->{ListingProductDetails}},
+ $xmlref->{ListingProductDetails};
+ $nof_items_added = 1;
+ }
+
+ return $nof_items_added;
+}
+
+##################################################
+sub properties {
+##################################################
+ my($self) = @_;
+
+ die "properties() not defined in ", __PACKAGE__, ". Use result() instead";
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Keyword.pm b/lib/Net/Amazon/Response/Keyword.pm
new file mode 100644
index 0000000..f6277d6
--- /dev/null
+++ b/lib/Net/Amazon/Response/Keyword.pm
@@ -0,0 +1,29 @@
+######################################################################
+package Net::Amazon::Response::Keyword;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use Data::Dumper;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Manufacturer.pm b/lib/Net/Amazon/Response/Manufacturer.pm
new file mode 100644
index 0000000..97ceebf
--- /dev/null
+++ b/lib/Net/Amazon/Response/Manufacturer.pm
@@ -0,0 +1,29 @@
+######################################################################
+package Net::Amazon::Response::Manufacturer;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use Data::Dumper;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Power.pm b/lib/Net/Amazon/Response/Power.pm
new file mode 100644
index 0000000..88cdd2d
--- /dev/null
+++ b/lib/Net/Amazon/Response/Power.pm
@@ -0,0 +1,28 @@
+######################################################################
+package Net::Amazon::Response::Power;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Seller.pm b/lib/Net/Amazon/Response/Seller.pm
new file mode 100644
index 0000000..f33ed50
--- /dev/null
+++ b/lib/Net/Amazon/Response/Seller.pm
@@ -0,0 +1,78 @@
+#############################################
+package Net::Amazon::Response::Seller;
+#############################################
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Result::Seller;
+use Data::Dumper;
+use Log::Log4perl qw(:easy);
+
+##############################
+sub new {
+##############################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub result {
+##################################################
+ my($self) = @_;
+
+ if($self->is_success()) {
+ DEBUG "Calling Seller constructor with ", Dumper($self);
+ return Net::Amazon::Result::Seller->new(
+ xmlref => $self->{xmlref}->{SellerSearchDetails}->[0],
+ );
+ }
+
+ return undef;
+}
+
+##################################################
+sub properties {
+##################################################
+ my($self) = @_;
+
+ die "properties() not defined in ", __PACKAGE__, ". Use result() instead";
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->result()->as_string();
+}
+
+##################################################
+sub xmlref_add {
+##################################################
+ my($self, $xmlref) = @_;
+
+ my $nof_items_added = 0;
+
+ unless(ref($self->{xmlref}) eq "HASH" &&
+ ref($self->{xmlref}->{SellerSearchDetails}) eq "ARRAY") {
+ $self->{xmlref}->{Details} = [];
+ }
+
+ if(ref($xmlref->{SellerSearchDetails}) eq "ARRAY") {
+ # Is it an array of items?
+ push @{$self->{xmlref}->{SellerSearchDetails}},
+ @{$xmlref->{SellerSearchDetails}};
+ $nof_items_added = scalar @{$xmlref->{SellerSearchDetails}};
+ } else {
+ # It is a single item
+ push @{$self->{xmlref}->{SellerSearchDetails}},
+ $xmlref->{SellerSearchDetails};
+ $nof_items_added = 1;
+ }
+
+ #DEBUG("xmlref_add (after):", Data::Dumper::Dumper($self));
+ return $nof_items_added;
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Similar.pm b/lib/Net/Amazon/Response/Similar.pm
new file mode 100644
index 0000000..27add88
--- /dev/null
+++ b/lib/Net/Amazon/Response/Similar.pm
@@ -0,0 +1,28 @@
+######################################################################
+package Net::Amazon::Response::Similar;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/TextStream.pm b/lib/Net/Amazon/Response/TextStream.pm
new file mode 100644
index 0000000..0cee872
--- /dev/null
+++ b/lib/Net/Amazon/Response/TextStream.pm
@@ -0,0 +1,28 @@
+######################################################################
+package Net::Amazon::Response::TextStream;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/UPC.pm b/lib/Net/Amazon/Response/UPC.pm
new file mode 100644
index 0000000..4fba4ad
--- /dev/null
+++ b/lib/Net/Amazon/Response/UPC.pm
@@ -0,0 +1,40 @@
+######################################################################
+package Net::Amazon::Response::UPC;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ my($property) = $self->properties;
+ return $property->as_string();
+}
+
+##################################################
+sub properties {
+##################################################
+ my($self) = @_;
+
+ my $property = Net::Amazon::Property::factory(
+ xmlref => $self->{xmlref}->{Details}->[0]);
+
+ return ($property);
+}
+
+1;
diff --git a/lib/Net/Amazon/Response/Wishlist.pm b/lib/Net/Amazon/Response/Wishlist.pm
new file mode 100644
index 0000000..15fd999
--- /dev/null
+++ b/lib/Net/Amazon/Response/Wishlist.pm
@@ -0,0 +1,29 @@
+######################################################################
+package Net::Amazon::Response::Wishlist;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon::Response);
+
+use Net::Amazon::Property;
+use Data::Dumper;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ my $self = $class->SUPER::new(%options);
+
+ bless $self, $class; # reconsecrate
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ return $self->SUPER::list_as_string($self->properties);
+}
+
+1;
diff --git a/lib/Net/Amazon/Result/Seller.pm b/lib/Net/Amazon/Result/Seller.pm
new file mode 100644
index 0000000..cb876a6
--- /dev/null
+++ b/lib/Net/Amazon/Result/Seller.pm
@@ -0,0 +1,130 @@
+######################################################################
+package Net::Amazon::Result::Seller;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon);
+
+use Data::Dumper;
+use Log::Log4perl qw(:easy);
+use Net::Amazon::Result::Seller::Listing;
+
+our @DEFAULT_ATTRIBUTES = qw(StoreName SellerNickname
+ NumberOfOpenListings StoreId);
+__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES;
+__PACKAGE__->make_array_accessor($_) for qw(listings);
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ if(!$options{xmlref}) {
+ die "Mandatory param xmlref missing";
+ }
+
+ my @listings = ();
+
+ my $self = {
+ %options,
+ };
+
+ bless $self, $class;
+
+ # Set default attributes
+ for my $attr (@DEFAULT_ATTRIBUTES) {
+ DEBUG "Setting attribute $attr to $options{xmlref}->{$attr}";
+ $self->$attr($options{xmlref}->{$attr});
+ }
+
+ for my $listing (@{$options{xmlref}->{ListingProductInfo}->{ListingProductDetails}}) {
+ push @listings,
+ Net::Amazon::Result::Seller::Listing->new(
+ xmlref => $listing);
+ }
+
+ $self->listings(\@listings);
+
+ return $self;
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ my $result = $self->StoreName() .
+ " (" .
+ $self->SellerNickname() .
+ "): " .
+ $self->NumberOfOpenListings() .
+ "";
+
+ return $result;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Result::Seller - Class for Seller info
+
+=head1 SYNOPSIS
+
+ use Net::Amazon;
+
+ # ...
+
+ if($resp->is_success()) {
+ print $resp->result()->as_string();
+ }
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Result::Seller> is a container for results on a seller
+search. It contains data on one particular seller (the one turned up by
+the previous search) and the listings this seller is currently running.
+
+=head2 METHODS
+
+=over 4
+
+=item StoreName()
+
+Name of the seller's store.
+
+=item SellerNickname()
+
+Seller's nickname.
+
+=item StoreId()
+
+ID of seller's store.
+
+=item NumberOfOpenListings()
+
+Number of listings the seller has currently open.
+
+=item listings()
+
+Returns an array of C<Net::Amazon::Result::Seller::Listing> objects.
+See the documentation of this class for details.
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2004 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
diff --git a/lib/Net/Amazon/Result/Seller/Listing.pm b/lib/Net/Amazon/Result/Seller/Listing.pm
new file mode 100644
index 0000000..c09ec08
--- /dev/null
+++ b/lib/Net/Amazon/Result/Seller/Listing.pm
@@ -0,0 +1,146 @@
+######################################################################
+package Net::Amazon::Result::Seller::Listing;
+######################################################################
+use warnings;
+use strict;
+use base qw(Net::Amazon);
+
+use Data::Dumper;
+use Log::Log4perl qw(:easy);
+
+our @DEFAULT_ATTRIBUTES = qw(
+ ExchangeStartDate ExchangeConditionType
+ ExchangeAsin ExchangeSellerId ExchangeEndDate ExchangePrice
+ ExchangeSellerRating ExchangeStatus ExchangeId ExchangeTitle
+ ExchangeQuantityAllocated ExchangeQuantity ExchangeSellerCountry
+ ExchangeSellerState ExchangeSellerNickname ExchangeFeaturedCategory
+ ExchangeAvailability ExchangeOfferingType ListingId ExchangeCondition
+ ExchangeDescription
+);
+
+__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES;
+
+##################################################
+sub new {
+##################################################
+ my($class, %options) = @_;
+
+ if(!$options{xmlref}) {
+ die "Mandatory param xmlref missing";
+ }
+
+ my $self = {
+ %options,
+ };
+
+ bless $self, $class;
+
+ DEBUG "Calling Listing with xmlref=", Dumper($options{xmlref});
+
+ # Set default attributes
+ for my $attr (@DEFAULT_ATTRIBUTES) {
+ $self->$attr($options{xmlref}->{$attr});
+ }
+
+ return $self;
+}
+
+##################################################
+sub as_string {
+##################################################
+ my($self) = @_;
+
+ my $result =
+ $self->ExchangeTitle() .
+ " (" .
+ $self->ExchangeAsin() .
+ "): " .
+ $self->ExchangePrice() .
+ "";
+
+ return $result;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::Amazon::Result::Seller::Listing - Class for a single Listing of a Seller
+
+=head1 SYNOPSIS
+
+ for($seller_search_resp->result()->seller()->listings()) {
+ print $_->as_string(), "\n";
+ }
+
+=head1 DESCRIPTION
+
+C<Net::Amazon::Result::Seller::Listing> is a container for a single listing
+owned by a third-party seller, who is represented by a
+C<Net::Amazon::Result::Seller> object.
+
+An object of this class is also returned by an C<Exchange> request, using
+C<Net::Amazon::Response::Exchange>'s C<result> method.
+
+=head2 METHODS
+
+=over 4
+
+=item ExchangeStartDate()
+
+=item ExchangeConditionType()
+
+=item ExchangeAsin()
+
+=item ExchangeSellerId()
+
+=item ExchangeEndDate()
+
+=item ExchangePrice()
+
+=item ExchangeSellerRating()
+
+=item ExchangeStatus()
+
+=item ExchangeId()
+
+=item ExchangeTitle()
+
+=item ExchangeQuantityAllocated()
+
+=item ExchangeQuantity()
+
+=item ExchangeSellerCountry()
+
+=item ExchangeSellerState()
+
+=item ExchangeSellerNickname()
+
+=item ExchangeFeaturedCategory()
+
+=item ExchangeAvailability()
+
+=item ExchangeOfferingType()
+
+=item ListingId()
+
+=item ExchangeCondition()
+
+=back
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+Mike Schilli, E<lt>m@perlmeister.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2004 by Mike Schilli E<lt>m@perlmeister.comE<gt>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut