| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | ############################################################################### | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | # This file copyright (c) 2006-2008 by Randy J. Ray, all rights reserved | 
| 4 |  |  |  |  |  |  | # | 
| 5 |  |  |  |  |  |  | # See "LICENSE" in the documentation for licensing and redistribution terms. | 
| 6 |  |  |  |  |  |  | # | 
| 7 |  |  |  |  |  |  | ############################################################################### | 
| 8 |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  | #   $Id: Books.pm 48 2008-04-06 10:38:11Z  $ | 
| 10 |  |  |  |  |  |  | # | 
| 11 |  |  |  |  |  |  | #   Description:    Specialization of the API class for book data. | 
| 12 |  |  |  |  |  |  | # | 
| 13 |  |  |  |  |  |  | #   Functions:      BUILD | 
| 14 |  |  |  |  |  |  | #                   copy | 
| 15 |  |  |  |  |  |  | #                   find | 
| 16 |  |  |  |  |  |  | #                   get_authors | 
| 17 |  |  |  |  |  |  | #                   set_authors | 
| 18 |  |  |  |  |  |  | #                   get_subjects | 
| 19 |  |  |  |  |  |  | #                   set_subjects | 
| 20 |  |  |  |  |  |  | #                   new | 
| 21 |  |  |  |  |  |  | #                   set_id | 
| 22 |  |  |  |  |  |  | #                   set_isbn | 
| 23 |  |  |  |  |  |  | #                   get_publisher | 
| 24 |  |  |  |  |  |  | #                   normalize_args | 
| 25 |  |  |  |  |  |  | #                   set_change_time | 
| 26 |  |  |  |  |  |  | #                   set_change_time_sec | 
| 27 |  |  |  |  |  |  | #                   set_price_time | 
| 28 |  |  |  |  |  |  | #                   set_price_time_sec | 
| 29 |  |  |  |  |  |  | #                   set_prices | 
| 30 |  |  |  |  |  |  | #                   set_marc | 
| 31 |  |  |  |  |  |  | # | 
| 32 |  |  |  |  |  |  | #   Libraries:      Class::Std | 
| 33 |  |  |  |  |  |  | #                   Error | 
| 34 |  |  |  |  |  |  | #                   Business::ISBN | 
| 35 |  |  |  |  |  |  | #                   WebService::ISBNDB::API | 
| 36 |  |  |  |  |  |  | # | 
| 37 |  |  |  |  |  |  | #   Global Consts:  $VERSION | 
| 38 |  |  |  |  |  |  | # | 
| 39 |  |  |  |  |  |  | ############################################################################### | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | package WebService::ISBNDB::API::Books; | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 3 |  |  | 3 |  | 19178 | use 5.006; | 
|  | 3 |  |  |  |  | 13 |  | 
|  | 3 |  |  |  |  | 119 |  | 
| 44 | 3 |  |  | 3 |  | 16 | use strict; | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 3 |  |  |  |  | 105 |  | 
| 45 | 3 |  |  | 3 |  | 18 | use warnings; | 
|  | 3 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 107 |  | 
| 46 | 3 |  |  | 3 |  | 20 | no warnings 'redefine'; | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 132 |  | 
| 47 | 3 |  |  | 3 |  | 16 | use vars qw($VERSION $CAN_PARSE_DATES); | 
|  | 3 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 207 |  | 
| 48 | 3 |  |  | 3 |  | 16 | use base 'WebService::ISBNDB::API'; | 
|  | 3 |  |  |  |  | 11 |  | 
|  | 3 |  |  |  |  | 298 |  | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 3 |  |  | 3 |  | 18 | use Class::Std; | 
|  | 3 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 34 |  | 
| 51 | 3 |  |  | 3 |  | 326 | use Error; | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 31 |  | 
| 52 | 3 |  |  | 3 |  | 3011 | use Business::ISBN; | 
|  | 3 |  |  |  |  | 140263 |  | 
|  | 3 |  |  |  |  | 198 |  | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | $VERSION = "0.33"; | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | BEGIN | 
| 57 |  |  |  |  |  |  | { | 
| 58 | 3 |  |  | 3 |  | 241 | eval "use Date::Parse"; | 
|  | 3 |  |  | 3 |  | 2898 |  | 
|  | 3 |  |  |  |  | 16102 |  | 
|  | 3 |  |  |  |  | 387 |  | 
| 59 | 3 | 50 |  |  |  | 3772 | $CAN_PARSE_DATES = ($@) ? 0 : 1; | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | # Attributes for the Books class | 
| 63 |  |  |  |  |  |  | my %id             : ATTR(:get   :init_arg             :default<>); | 
| 64 |  |  |  |  |  |  | my %isbn           : ATTR(:get :init_arg           :default<>); | 
| 65 |  |  |  |  |  |  | my %title          : ATTR(:name                         :default<>); | 
| 66 |  |  |  |  |  |  | my %longtitle      : ATTR(:name                     :default<>); | 
| 67 |  |  |  |  |  |  | my %authors_text   : ATTR(:name                  :default<>); | 
| 68 |  |  |  |  |  |  | my %authors        : ATTR(:init_arg                   :default<>); | 
| 69 |  |  |  |  |  |  | my %publisher_text : ATTR(:name                :default<>); | 
| 70 |  |  |  |  |  |  | my %publisher      : ATTR(:init_arg :set :default<>); | 
| 71 |  |  |  |  |  |  | my %subjects       : ATTR(:init_arg                  :default<>); | 
| 72 |  |  |  |  |  |  | my %dewey_decimal  : ATTR(:name                 :default<>); | 
| 73 |  |  |  |  |  |  | my %dewey_decimal_normalized : ATTR(:name :default<>); | 
| 74 |  |  |  |  |  |  | my %lcc_number     : ATTR(:name                    :default<>); | 
| 75 |  |  |  |  |  |  | my %language       : ATTR(:name                      :default<>); | 
| 76 |  |  |  |  |  |  | my %physical_description_text : ATTR(:name :default<>); | 
| 77 |  |  |  |  |  |  | my %edition_info   : ATTR(:name                  :default<>); | 
| 78 |  |  |  |  |  |  | my %change_time    : ATTR(:init_arg :get :default<>); | 
| 79 |  |  |  |  |  |  | my %change_time_sec : ATTR(:init_arg :get :default<>); | 
| 80 |  |  |  |  |  |  | my %price_time     : ATTR(:init_arg :get :default<>); | 
| 81 |  |  |  |  |  |  | my %price_time_sec : ATTR(:init_arg :get :default<>); | 
| 82 |  |  |  |  |  |  | my %summary        : ATTR(:name                       :default<>); | 
| 83 |  |  |  |  |  |  | my %notes          : ATTR(:name                         :default<>); | 
| 84 |  |  |  |  |  |  | my %urlstext       : ATTR(:name                      :default<>); | 
| 85 |  |  |  |  |  |  | my %awardstext     : ATTR(:name                    :default<>); | 
| 86 |  |  |  |  |  |  | my %prices         : ATTR(:init_arg :get       :default<>); | 
| 87 |  |  |  |  |  |  | my %marc           : ATTR(:init_arg   :get         :default<>); | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | ############################################################################### | 
| 90 |  |  |  |  |  |  | # | 
| 91 |  |  |  |  |  |  | #   Sub Name:       new | 
| 92 |  |  |  |  |  |  | # | 
| 93 |  |  |  |  |  |  | #   Description:    Pass off to the super-class constructor, which handles | 
| 94 |  |  |  |  |  |  | #                   the special cases for arguments. | 
| 95 |  |  |  |  |  |  | # | 
| 96 |  |  |  |  |  |  | ############################################################################### | 
| 97 |  |  |  |  |  |  | sub new | 
| 98 |  |  |  |  |  |  | { | 
| 99 | 3 |  |  | 3 |  | 1965 | shift->SUPER::new(@_); | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | ############################################################################### | 
| 103 |  |  |  |  |  |  | # | 
| 104 |  |  |  |  |  |  | #   Sub Name:       BUILD | 
| 105 |  |  |  |  |  |  | # | 
| 106 |  |  |  |  |  |  | #   Description:    Builder for this class. See Class::Std. | 
| 107 |  |  |  |  |  |  | # | 
| 108 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 109 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 110 |  |  |  |  |  |  | #                   $id       in      scalar    This object's unique ID | 
| 111 |  |  |  |  |  |  | #                   $args     in      hashref   The set of arguments currently | 
| 112 |  |  |  |  |  |  | #                                                 being considered for the | 
| 113 |  |  |  |  |  |  | #                                                 constructor. | 
| 114 |  |  |  |  |  |  | # | 
| 115 |  |  |  |  |  |  | #   Returns:        Success:    void | 
| 116 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 117 |  |  |  |  |  |  | # | 
| 118 |  |  |  |  |  |  | ############################################################################### | 
| 119 |  |  |  |  |  |  | sub BUILD | 
| 120 |  |  |  |  |  |  | { | 
| 121 | 2 |  |  | 2 | 1 | 227 | my ($self, $id, $args) = @_; | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 2 |  |  |  |  | 8 | $self->set_type('Books'); | 
| 124 |  |  |  |  |  |  |  | 
| 125 | 2 | 50 |  |  |  | 5 | if ($CAN_PARSE_DATES) | 
| 126 |  |  |  |  |  |  | { | 
| 127 | 2 | 50 | 33 |  |  | 10 | $args->{change_time_sec} = str2time($args->{change_time}) | 
| 128 |  |  |  |  |  |  | if ($args->{change_time} and ! $args->{change_time_sec}); | 
| 129 | 2 | 50 | 33 |  |  | 7 | $args->{price_time_sec} = str2time($args->{price_time}) | 
| 130 |  |  |  |  |  |  | if ($args->{price_time} and ! $args->{price_time_sec}); | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 2 |  |  |  |  | 5 | return; | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | ############################################################################### | 
| 137 |  |  |  |  |  |  | # | 
| 138 |  |  |  |  |  |  | #   Sub Name:       find | 
| 139 |  |  |  |  |  |  | # | 
| 140 |  |  |  |  |  |  | #   Description:    Find a single record using the passed-in search criteria. | 
| 141 |  |  |  |  |  |  | #                   Most of the work is done by the super-class: this method | 
| 142 |  |  |  |  |  |  | #                   turns a single-argument call into a proper hashref, and/or | 
| 143 |  |  |  |  |  |  | #                   turns user-supplied arguments into those recognized by the | 
| 144 |  |  |  |  |  |  | #                   API. | 
| 145 |  |  |  |  |  |  | # | 
| 146 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 147 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 148 |  |  |  |  |  |  | #                   $args     in      variable  See text | 
| 149 |  |  |  |  |  |  | # | 
| 150 |  |  |  |  |  |  | #   Returns:        Success:    result from SUPER::find | 
| 151 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 152 |  |  |  |  |  |  | # | 
| 153 |  |  |  |  |  |  | ############################################################################### | 
| 154 |  |  |  |  |  |  | sub find | 
| 155 |  |  |  |  |  |  | { | 
| 156 | 1 |  |  | 1 | 1 | 2 | my ($self, $args) = @_; | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | # First, see if we were passed a single scalar for an argument. If so, it | 
| 159 |  |  |  |  |  |  | # needs to become either an ISBN or title argument. | 
| 160 | 1 | 50 |  |  |  | 4 | if (! ref($args)) | 
| 161 |  |  |  |  |  |  | { | 
| 162 | 1 |  |  |  |  | 1 | my $obj; | 
| 163 | 1 | 50 | 33 |  |  | 10 | if (ref($obj = Business::ISBN->new($args)) and | 
| 164 |  |  |  |  |  |  | $obj->is_valid_checksum() eq Business::ISBN::GOOD_ISBN) | 
| 165 |  |  |  |  |  |  | { | 
| 166 | 1 |  |  |  |  | 331 | $args = { isbn => $args }; | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  | else | 
| 169 |  |  |  |  |  |  | { | 
| 170 | 0 |  |  |  |  | 0 | $args = { book_id => $args }; | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 | 1 |  |  |  |  | 18 | $self->SUPER::find($args); | 
| 175 |  |  |  |  |  |  | } | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | ############################################################################### | 
| 178 |  |  |  |  |  |  | # | 
| 179 |  |  |  |  |  |  | #   Sub Name:       normalize_args | 
| 180 |  |  |  |  |  |  | # | 
| 181 |  |  |  |  |  |  | #   Description:    Normalize the contents of the $args hash reference, turning | 
| 182 |  |  |  |  |  |  | #                   the user-visible (and user-friendlier) arguments into the | 
| 183 |  |  |  |  |  |  | #                   arguments that the API expects. | 
| 184 |  |  |  |  |  |  | # | 
| 185 |  |  |  |  |  |  | #                   Also adds some "results" values, to tailor the returned | 
| 186 |  |  |  |  |  |  | #                   content. | 
| 187 |  |  |  |  |  |  | # | 
| 188 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 189 |  |  |  |  |  |  | #                   $class    in      scalar    Object ref or class name | 
| 190 |  |  |  |  |  |  | #                   $args     in      hashref   Reference to the arguments hash | 
| 191 |  |  |  |  |  |  | # | 
| 192 |  |  |  |  |  |  | #   Returns:        Success:    $args (changed) | 
| 193 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 194 |  |  |  |  |  |  | # | 
| 195 |  |  |  |  |  |  | ############################################################################### | 
| 196 |  |  |  |  |  |  | sub normalize_args | 
| 197 |  |  |  |  |  |  | { | 
| 198 | 1 |  |  | 1 | 1 | 2 | my ($class, $args) = @_; | 
| 199 |  |  |  |  |  |  |  | 
| 200 | 1 |  |  |  |  | 2 | my ($key, $value, @keys, $count, $results, %seen); | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | # Turn the collection of arguments into a set that the isbndb.com API can | 
| 203 |  |  |  |  |  |  | # use. Each key/value pair has to become a pair of the form "indexX" and | 
| 204 |  |  |  |  |  |  | # "valueX". Some keys, like author and publisher, have to be handled with | 
| 205 |  |  |  |  |  |  | # more attention. | 
| 206 | 1 |  |  |  |  | 3 | @keys = keys %$args; | 
| 207 | 1 |  |  |  |  | 2 | $count = 0; # Used to gradually increment the "indexX" and "valueX" keys | 
| 208 | 1 |  |  |  |  | 2 | foreach $key (@keys) | 
| 209 |  |  |  |  |  |  | { | 
| 210 |  |  |  |  |  |  | # If we see "api_key", it means that WebService::ISBNDB::API::search | 
| 211 |  |  |  |  |  |  | # curried it into the arglist due to the type-level search being | 
| 212 |  |  |  |  |  |  | # called as a static method. | 
| 213 | 1 | 50 |  |  |  | 3 | next if $key eq 'api_key'; | 
| 214 | 1 |  |  |  |  | 2 | $value = $args->{$key}; | 
| 215 | 1 |  |  |  |  | 3 | delete $args->{$key}; | 
| 216 | 1 |  |  |  |  | 1 | $count++; | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | # If the key is 'author', it may be a name or an Authors object. If it | 
| 219 |  |  |  |  |  |  | # is not an object, it has to become a "full" key, which is very non- | 
| 220 |  |  |  |  |  |  | # specific. | 
| 221 | 1 | 50 |  |  |  | 3 | if ($key eq 'author') | 
| 222 |  |  |  |  |  |  | { | 
| 223 | 0 | 0 |  |  |  | 0 | if (ref $value) | 
| 224 |  |  |  |  |  |  | { | 
| 225 | 0 | 0 |  |  |  | 0 | if ($value->isa('WebService::ISBNDB::API::Authors')) | 
| 226 |  |  |  |  |  |  | { | 
| 227 | 0 |  |  |  |  | 0 | $args->{"index$count"} = 'person_id'; | 
| 228 | 0 |  |  |  |  | 0 | $args->{"value$count"} = $value->get_id; | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  | else | 
| 231 |  |  |  |  |  |  | { | 
| 232 | 0 |  |  |  |  | 0 | throw Error::Simple("Value for argument '$key' must be " . | 
| 233 |  |  |  |  |  |  | 'string or ' . | 
| 234 |  |  |  |  |  |  | 'WebService::ISBNDB::API::Authors' . | 
| 235 |  |  |  |  |  |  | ' derivative'); | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  | else | 
| 239 |  |  |  |  |  |  | { | 
| 240 | 0 |  |  |  |  | 0 | $args->{"index$count"} = 'combined'; | 
| 241 | 0 |  |  |  |  | 0 | $args->{"value$count"} = $value; | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 0 |  |  |  |  | 0 | next; | 
| 245 |  |  |  |  |  |  | } | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | # If the key is 'publisher', treat the same as with author | 
| 248 | 1 | 50 |  |  |  | 3 | if ($key eq 'publisher') | 
| 249 |  |  |  |  |  |  | { | 
| 250 | 0 | 0 |  |  |  | 0 | if (ref $value) | 
| 251 |  |  |  |  |  |  | { | 
| 252 | 0 | 0 |  |  |  | 0 | if ($value->isa('WebService::ISBNDB::API::Publishers')) | 
| 253 |  |  |  |  |  |  | { | 
| 254 | 0 |  |  |  |  | 0 | $args->{"index$count"} = 'publisher_id'; | 
| 255 | 0 |  |  |  |  | 0 | $args->{"value$count"} = $value->get_id; | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  | else | 
| 258 |  |  |  |  |  |  | { | 
| 259 | 0 |  |  |  |  | 0 | throw Error::Simple("Value for argument '$key' must be " . | 
| 260 |  |  |  |  |  |  | 'string or ' . | 
| 261 |  |  |  |  |  |  | 'WebService::ISBNDB::API::Publishers' . | 
| 262 |  |  |  |  |  |  | ' derivative'); | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  | else | 
| 266 |  |  |  |  |  |  | { | 
| 267 | 0 |  |  |  |  | 0 | $args->{"index$count"} = 'combined'; | 
| 268 | 0 |  |  |  |  | 0 | $args->{"value$count"} = $value; | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 | 0 |  |  |  |  | 0 | next; | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | # A subject can be an object or an ID. | 
| 275 | 1 | 50 |  |  |  | 3 | if ($key eq 'subject') | 
| 276 |  |  |  |  |  |  | { | 
| 277 | 0 | 0 |  |  |  | 0 | if (ref $value) | 
| 278 |  |  |  |  |  |  | { | 
| 279 | 0 | 0 |  |  |  | 0 | if ($value->isa('WebService::ISBNDB::API::Subjects')) | 
| 280 |  |  |  |  |  |  | { | 
| 281 | 0 |  |  |  |  | 0 | $args->{"index$count"} = 'subject_id'; | 
| 282 | 0 |  |  |  |  | 0 | $args->{"value$count"} = $value->get_id; | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  | else | 
| 285 |  |  |  |  |  |  | { | 
| 286 | 0 |  |  |  |  | 0 | throw Error::Simple("Value for argument '$key' must be " . | 
| 287 |  |  |  |  |  |  | 'string or ' . | 
| 288 |  |  |  |  |  |  | 'WebService::ISBNDB::API::Subjects ' . | 
| 289 |  |  |  |  |  |  | 'derivative'); | 
| 290 |  |  |  |  |  |  | } | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  | else | 
| 293 |  |  |  |  |  |  | { | 
| 294 | 0 |  |  |  |  | 0 | $args->{"index$count"} = 'subject_id'; | 
| 295 | 0 |  |  |  |  | 0 | $args->{"value$count"} = $value; | 
| 296 |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  |  | 
| 298 | 0 |  |  |  |  | 0 | next; | 
| 299 |  |  |  |  |  |  | } | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | # These are the only other allowed search-keys | 
| 302 | 1 | 50 |  |  |  | 19 | if ($key =~ | 
| 303 |  |  |  |  |  |  | /^(:?dewey_decimal|lcc_number|full|combined|title|isbn|book_id)$/) | 
| 304 |  |  |  |  |  |  | { | 
| 305 | 1 |  |  |  |  | 3 | $args->{"index$count"} = $key; | 
| 306 | 1 |  |  |  |  | 4 | $args->{"value$count"} = $value; | 
| 307 |  |  |  |  |  |  |  | 
| 308 | 1 |  |  |  |  | 2 | next; | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  |  | 
| 311 | 0 |  |  |  |  | 0 | throw Error::Simple("'$key' is not a valid search-key for books"); | 
| 312 |  |  |  |  |  |  | } | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | # Add the "results" values that we want | 
| 315 | 1 |  |  |  |  | 4 | $args->{results} = [ qw(details prices marc texts subjects authors) ]; | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 1 |  |  |  |  | 9 | $args; | 
| 318 |  |  |  |  |  |  | } | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | ############################################################################### | 
| 321 |  |  |  |  |  |  | # | 
| 322 |  |  |  |  |  |  | #   Sub Name:       set_id | 
| 323 |  |  |  |  |  |  | # | 
| 324 |  |  |  |  |  |  | #   Description:    Set the ID attribute on the object. Done manually so that | 
| 325 |  |  |  |  |  |  | #                   we can restrict it to this package. | 
| 326 |  |  |  |  |  |  | # | 
| 327 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 328 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 329 |  |  |  |  |  |  | #                   $id       in      scalar    ID, taken from isbndb.com data | 
| 330 |  |  |  |  |  |  | # | 
| 331 |  |  |  |  |  |  | #   Globals:        %id | 
| 332 |  |  |  |  |  |  | # | 
| 333 |  |  |  |  |  |  | #   Returns:        $self | 
| 334 |  |  |  |  |  |  | # | 
| 335 |  |  |  |  |  |  | ############################################################################### | 
| 336 |  |  |  |  |  |  | sub set_id : RESTRICTED | 
| 337 |  |  |  |  |  |  | { | 
| 338 | 0 |  |  | 0 | 1 | 0 | my ($self, $id) = @_; | 
| 339 |  |  |  |  |  |  |  | 
| 340 | 0 |  |  |  |  | 0 | $id{ident $self} = $id; | 
| 341 | 0 |  |  |  |  | 0 | $self; | 
| 342 | 3 |  |  | 3 |  | 29 | } | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 3 |  |  |  |  | 81 |  | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | ############################################################################### | 
| 345 |  |  |  |  |  |  | # | 
| 346 |  |  |  |  |  |  | #   Sub Name:       set_isbn | 
| 347 |  |  |  |  |  |  | # | 
| 348 |  |  |  |  |  |  | #   Description:    Set the ISBN for this object. Tests the new value before | 
| 349 |  |  |  |  |  |  | #                   assigning it. | 
| 350 |  |  |  |  |  |  | # | 
| 351 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 352 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 353 |  |  |  |  |  |  | #                   $isbn     in      scalar    New ISBN value | 
| 354 |  |  |  |  |  |  | # | 
| 355 |  |  |  |  |  |  | #   Globals:        %isbn | 
| 356 |  |  |  |  |  |  | # | 
| 357 |  |  |  |  |  |  | #   Returns:        Success:    $self | 
| 358 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 359 |  |  |  |  |  |  | # | 
| 360 |  |  |  |  |  |  | ############################################################################### | 
| 361 |  |  |  |  |  |  | sub set_isbn | 
| 362 |  |  |  |  |  |  | { | 
| 363 | 0 |  |  | 0 | 1 |  | my ($self, $isbn) = @_; | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 0 | 0 |  |  |  |  | throw Error::Simple("The value '$isbn' is not a valid ISBN") | 
| 366 |  |  |  |  |  |  | unless (Business::ISBN->new($isbn)->is_valid_checksum eq | 
| 367 |  |  |  |  |  |  | Business::ISBN::GOOD_ISBN); | 
| 368 | 0 |  |  |  |  |  | $isbn{ident $self} = $isbn; | 
| 369 |  |  |  |  |  |  |  | 
| 370 | 0 |  |  |  |  |  | $self; | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | ############################################################################### | 
| 374 |  |  |  |  |  |  | # | 
| 375 |  |  |  |  |  |  | #   Sub Name:       get_publisher | 
| 376 |  |  |  |  |  |  | # | 
| 377 |  |  |  |  |  |  | #   Description:    Retrieve the "publisher" attribute for this object. If the | 
| 378 |  |  |  |  |  |  | #                   value is a string rather than a reference, assume that it | 
| 379 |  |  |  |  |  |  | #                   is an ID, and fetch the actual Publisher object before | 
| 380 |  |  |  |  |  |  | #                   returning the value. | 
| 381 |  |  |  |  |  |  | # | 
| 382 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 383 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 384 |  |  |  |  |  |  | # | 
| 385 |  |  |  |  |  |  | #   Globals:        %publisher | 
| 386 |  |  |  |  |  |  | # | 
| 387 |  |  |  |  |  |  | #   Returns:        Success:    Publisher object | 
| 388 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 389 |  |  |  |  |  |  | # | 
| 390 |  |  |  |  |  |  | ############################################################################### | 
| 391 |  |  |  |  |  |  | sub get_publisher | 
| 392 |  |  |  |  |  |  | { | 
| 393 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 394 |  |  |  |  |  |  |  | 
| 395 | 0 |  |  |  |  |  | my $id = ident $self; | 
| 396 |  |  |  |  |  |  |  | 
| 397 | 0 |  |  |  |  |  | my $publisher = $publisher{$id}; | 
| 398 | 0 | 0 |  |  |  |  | unless (ref $publisher) | 
| 399 |  |  |  |  |  |  | { | 
| 400 | 0 |  |  |  |  |  | my $class = $self->class_for_type('Publishers'); | 
| 401 |  |  |  |  |  |  | # Make sure it's loaded | 
| 402 | 0 |  |  |  |  |  | eval "require $class;"; | 
| 403 | 0 |  |  |  |  |  | $publisher = $class->find({ publisher_id => $publisher }); | 
| 404 | 0 |  |  |  |  |  | $publisher{$id} = $publisher; | 
| 405 |  |  |  |  |  |  | } | 
| 406 |  |  |  |  |  |  |  | 
| 407 | 0 |  |  |  |  |  | $publisher; | 
| 408 |  |  |  |  |  |  | } | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | ############################################################################### | 
| 411 |  |  |  |  |  |  | # | 
| 412 |  |  |  |  |  |  | #   Sub Name:       set_authors | 
| 413 |  |  |  |  |  |  | # | 
| 414 |  |  |  |  |  |  | #   Description:    Set the list of Authors objects for this instance. The list | 
| 415 |  |  |  |  |  |  | #                   will initially be a list of IDs, taken from the attributes | 
| 416 |  |  |  |  |  |  | #                   of the XML. Only upon read-access (via get_authors) will | 
| 417 |  |  |  |  |  |  | #                   the list be turned into real objects. | 
| 418 |  |  |  |  |  |  | # | 
| 419 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 420 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 421 |  |  |  |  |  |  | #                   $list     in      ref       List-reference of author data | 
| 422 |  |  |  |  |  |  | # | 
| 423 |  |  |  |  |  |  | #   Globals:        %authors | 
| 424 |  |  |  |  |  |  | # | 
| 425 |  |  |  |  |  |  | #   Returns:        Success:    $self | 
| 426 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 427 |  |  |  |  |  |  | # | 
| 428 |  |  |  |  |  |  | ############################################################################### | 
| 429 |  |  |  |  |  |  | sub set_authors | 
| 430 |  |  |  |  |  |  | { | 
| 431 | 0 |  |  | 0 | 1 |  | my ($self, $list) = @_; | 
| 432 |  |  |  |  |  |  |  | 
| 433 | 0 | 0 |  |  |  |  | throw Error::Simple("Argument to 'set_authors' must be a list reference") | 
| 434 |  |  |  |  |  |  | unless (ref($list) eq 'ARRAY'); | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | # Make a copy of the list | 
| 437 | 0 |  |  |  |  |  | $authors{ident $self} = [ @$list ]; | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 0 |  |  |  |  |  | $self; | 
| 440 |  |  |  |  |  |  | } | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | ############################################################################### | 
| 443 |  |  |  |  |  |  | # | 
| 444 |  |  |  |  |  |  | #   Sub Name:       get_authors | 
| 445 |  |  |  |  |  |  | # | 
| 446 |  |  |  |  |  |  | #   Description:    Return a list-reference of the authors of the book. If this | 
| 447 |  |  |  |  |  |  | #                   is the first such request, then the author values are going | 
| 448 |  |  |  |  |  |  | #                   to be scalars, not objects, and must be converted to | 
| 449 |  |  |  |  |  |  | #                   objects before being returned. | 
| 450 |  |  |  |  |  |  | # | 
| 451 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 452 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 453 |  |  |  |  |  |  | # | 
| 454 |  |  |  |  |  |  | #   Globals:        %authors | 
| 455 |  |  |  |  |  |  | # | 
| 456 |  |  |  |  |  |  | #   Returns:        Success:    list-reference of data | 
| 457 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 458 |  |  |  |  |  |  | # | 
| 459 |  |  |  |  |  |  | ############################################################################### | 
| 460 |  |  |  |  |  |  | sub get_authors | 
| 461 |  |  |  |  |  |  | { | 
| 462 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 463 |  |  |  |  |  |  |  | 
| 464 | 0 |  |  |  |  |  | my $authors = $authors{ident $self}; | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | # If the first element is not a reference, we need to transform the list | 
| 467 | 0 | 0 |  |  |  |  | if (grep(! ref($_), @$authors)) | 
| 468 |  |  |  |  |  |  | { | 
| 469 | 0 |  |  |  |  |  | my $class = $self->class_for_type('Authors'); | 
| 470 |  |  |  |  |  |  | # Make sure it's loaded | 
| 471 | 0 |  |  |  |  |  | eval "require $class;"; | 
| 472 | 0 |  |  |  |  |  | my $auth_id; | 
| 473 |  |  |  |  |  |  |  | 
| 474 | 0 |  |  |  |  |  | for (0 .. $#$authors) | 
| 475 |  |  |  |  |  |  | { | 
| 476 | 0 | 0 |  |  |  |  | unless (ref($auth_id = $authors->[$_])) | 
| 477 |  |  |  |  |  |  | { | 
| 478 | 0 | 0 |  |  |  |  | throw Error::Simple("No author found for ID '$auth_id'") | 
| 479 |  |  |  |  |  |  | unless ref($authors->[$_] = $class->find({ id => | 
| 480 |  |  |  |  |  |  | $auth_id })); | 
| 481 |  |  |  |  |  |  | } | 
| 482 |  |  |  |  |  |  | } | 
| 483 |  |  |  |  |  |  | } | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | # Make a copy, so the real reference doesn't get altered | 
| 486 | 0 |  |  |  |  |  | [ @$authors ]; | 
| 487 |  |  |  |  |  |  | } | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | ############################################################################### | 
| 490 |  |  |  |  |  |  | # | 
| 491 |  |  |  |  |  |  | #   Sub Name:       set_subjects | 
| 492 |  |  |  |  |  |  | # | 
| 493 |  |  |  |  |  |  | #   Description:    Set the list of Subjects objects for this instance. The | 
| 494 |  |  |  |  |  |  | #                   list will initially be a list of IDs, taken from the | 
| 495 |  |  |  |  |  |  | #                   attributes of the XML. Only upon read-access (via | 
| 496 |  |  |  |  |  |  | #                   get_subjects) will the list be turned into real objects. | 
| 497 |  |  |  |  |  |  | # | 
| 498 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 499 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 500 |  |  |  |  |  |  | #                   $list     in      ref       List-reference of category data | 
| 501 |  |  |  |  |  |  | # | 
| 502 |  |  |  |  |  |  | #   Globals:        %subjects | 
| 503 |  |  |  |  |  |  | # | 
| 504 |  |  |  |  |  |  | #   Returns:        Success:    $self | 
| 505 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 506 |  |  |  |  |  |  | # | 
| 507 |  |  |  |  |  |  | ############################################################################### | 
| 508 |  |  |  |  |  |  | sub set_subjects | 
| 509 |  |  |  |  |  |  | { | 
| 510 | 0 |  |  | 0 | 1 |  | my ($self, $list) = @_; | 
| 511 |  |  |  |  |  |  |  | 
| 512 | 0 | 0 |  |  |  |  | throw Error::Simple("Argument to 'set_subjects' must be a list reference") | 
| 513 |  |  |  |  |  |  | unless (ref($list) eq 'ARRAY'); | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | # Make a copy of the list | 
| 516 | 0 |  |  |  |  |  | $subjects{ident $self} = [ @$list ]; | 
| 517 |  |  |  |  |  |  |  | 
| 518 | 0 |  |  |  |  |  | $self; | 
| 519 |  |  |  |  |  |  | } | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | ############################################################################### | 
| 522 |  |  |  |  |  |  | # | 
| 523 |  |  |  |  |  |  | #   Sub Name:       get_subjects | 
| 524 |  |  |  |  |  |  | # | 
| 525 |  |  |  |  |  |  | #   Description:    Return a list-reference of the book subjects. If this is | 
| 526 |  |  |  |  |  |  | #                   the first such request, then the subject values are going | 
| 527 |  |  |  |  |  |  | #                   to be scalars, not objects, and must be converted to | 
| 528 |  |  |  |  |  |  | #                   objects before being returned. | 
| 529 |  |  |  |  |  |  | # | 
| 530 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 531 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 532 |  |  |  |  |  |  | # | 
| 533 |  |  |  |  |  |  | #   Globals:        %subjects | 
| 534 |  |  |  |  |  |  | # | 
| 535 |  |  |  |  |  |  | #   Returns:        Success:    list-reference of data | 
| 536 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 537 |  |  |  |  |  |  | # | 
| 538 |  |  |  |  |  |  | ############################################################################### | 
| 539 |  |  |  |  |  |  | sub get_subjects | 
| 540 |  |  |  |  |  |  | { | 
| 541 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 542 |  |  |  |  |  |  |  | 
| 543 | 0 |  |  |  |  |  | my $subjects = $subjects{ident $self}; | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | # If any element is not a reference, we need to transform the list | 
| 546 | 0 | 0 |  |  |  |  | if (grep(! ref($_), @$subjects)) | 
| 547 |  |  |  |  |  |  | { | 
| 548 | 0 |  |  |  |  |  | my $class = $self->class_for_type('Subjects'); | 
| 549 |  |  |  |  |  |  | # Make sure it's loaded | 
| 550 | 0 |  |  |  |  |  | eval "require $class;"; | 
| 551 | 0 |  |  |  |  |  | my $subj_id; | 
| 552 |  |  |  |  |  |  |  | 
| 553 | 0 |  |  |  |  |  | for (0 .. $#$subjects) | 
| 554 |  |  |  |  |  |  | { | 
| 555 | 0 | 0 |  |  |  |  | unless (ref($subj_id = $subjects->[$_])) | 
| 556 |  |  |  |  |  |  | { | 
| 557 | 0 | 0 |  |  |  |  | throw Error::Simple("No subject found for ID '$subj_id'") | 
| 558 |  |  |  |  |  |  | unless ref($subjects->[$_] = $class->find({ id => | 
| 559 |  |  |  |  |  |  | $subj_id })); | 
| 560 |  |  |  |  |  |  | } | 
| 561 |  |  |  |  |  |  | } | 
| 562 |  |  |  |  |  |  | } | 
| 563 |  |  |  |  |  |  |  | 
| 564 |  |  |  |  |  |  | # Make a copy, so the real reference doesn't get altered | 
| 565 | 0 |  |  |  |  |  | [ @$subjects ]; | 
| 566 |  |  |  |  |  |  | } | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | ############################################################################### | 
| 569 |  |  |  |  |  |  | # | 
| 570 |  |  |  |  |  |  | #   Sub Name:       set_change_time | 
| 571 |  |  |  |  |  |  | # | 
| 572 |  |  |  |  |  |  | #   Description:    Set the change_time value; also update change_time_sec if | 
| 573 |  |  |  |  |  |  | #                   $CAN_PARSE_DATES is true. | 
| 574 |  |  |  |  |  |  | # | 
| 575 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 576 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 577 |  |  |  |  |  |  | #                   $time     in      scalar    Time-string | 
| 578 |  |  |  |  |  |  | # | 
| 579 |  |  |  |  |  |  | #   Globals:        $CAN_PARSE_DATES | 
| 580 |  |  |  |  |  |  | #                   %change_time | 
| 581 |  |  |  |  |  |  | #                   %change_time_sec | 
| 582 |  |  |  |  |  |  | # | 
| 583 |  |  |  |  |  |  | #   Returns:        $self | 
| 584 |  |  |  |  |  |  | # | 
| 585 |  |  |  |  |  |  | ############################################################################### | 
| 586 |  |  |  |  |  |  | sub set_change_time | 
| 587 |  |  |  |  |  |  | { | 
| 588 | 0 |  |  | 0 | 1 |  | my ($self, $time) = @_; | 
| 589 | 0 |  |  |  |  |  | my $id = ident $self; | 
| 590 |  |  |  |  |  |  |  | 
| 591 | 0 |  |  |  |  |  | $change_time{$id} = $time; | 
| 592 | 0 | 0 |  |  |  |  | $change_time_sec{$id} = str2time($time) if $CAN_PARSE_DATES; | 
| 593 |  |  |  |  |  |  |  | 
| 594 | 0 |  |  |  |  |  | $self; | 
| 595 |  |  |  |  |  |  | } | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | ############################################################################### | 
| 598 |  |  |  |  |  |  | # | 
| 599 |  |  |  |  |  |  | #   Sub Name:       set_change_time_sec | 
| 600 |  |  |  |  |  |  | # | 
| 601 |  |  |  |  |  |  | #   Description:    Set the change_time_sec value; also updates change_time. | 
| 602 |  |  |  |  |  |  | # | 
| 603 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 604 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 605 |  |  |  |  |  |  | #                   $time     in      scalar    Time, in seconds | 
| 606 |  |  |  |  |  |  | # | 
| 607 |  |  |  |  |  |  | #   Globals:        %change_time | 
| 608 |  |  |  |  |  |  | #                   %change_time_sec | 
| 609 |  |  |  |  |  |  | # | 
| 610 |  |  |  |  |  |  | #   Returns:        $self | 
| 611 |  |  |  |  |  |  | # | 
| 612 |  |  |  |  |  |  | ############################################################################### | 
| 613 |  |  |  |  |  |  | sub set_change_time_sec | 
| 614 |  |  |  |  |  |  | { | 
| 615 | 0 |  |  | 0 | 1 |  | my ($self, $time) = @_; | 
| 616 | 0 |  |  |  |  |  | my $id = ident $self; | 
| 617 |  |  |  |  |  |  |  | 
| 618 | 0 |  |  |  |  |  | $change_time_sec{$id} = $time; | 
| 619 | 0 |  |  |  |  |  | my @parts = localtime $time; | 
| 620 | 0 |  |  |  |  |  | $change_time{$id} = sprintf("%4d-%02d-%02dT%02d:%02d:%02dZ", | 
| 621 |  |  |  |  |  |  | $parts[5] + 1900, # year | 
| 622 |  |  |  |  |  |  | $parts[4] + 1,    # month | 
| 623 |  |  |  |  |  |  | $parts[3],        # day | 
| 624 |  |  |  |  |  |  | @parts[2,1,0]);   # hours, mins, secs | 
| 625 |  |  |  |  |  |  |  | 
| 626 | 0 |  |  |  |  |  | $self; | 
| 627 |  |  |  |  |  |  | } | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | ############################################################################### | 
| 630 |  |  |  |  |  |  | # | 
| 631 |  |  |  |  |  |  | #   Sub Name:       set_price_time | 
| 632 |  |  |  |  |  |  | # | 
| 633 |  |  |  |  |  |  | #   Description:    Set the price_time value; also update price_time_sec if | 
| 634 |  |  |  |  |  |  | #                   $CAN_PARSE_DATES is true. | 
| 635 |  |  |  |  |  |  | # | 
| 636 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 637 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 638 |  |  |  |  |  |  | #                   $time     in      scalar    Time-string | 
| 639 |  |  |  |  |  |  | # | 
| 640 |  |  |  |  |  |  | #   Globals:        $CAN_PARSE_DATES | 
| 641 |  |  |  |  |  |  | #                   %price_time | 
| 642 |  |  |  |  |  |  | #                   %price_time_sec | 
| 643 |  |  |  |  |  |  | # | 
| 644 |  |  |  |  |  |  | #   Returns:        $self | 
| 645 |  |  |  |  |  |  | # | 
| 646 |  |  |  |  |  |  | ############################################################################### | 
| 647 |  |  |  |  |  |  | sub set_price_time | 
| 648 |  |  |  |  |  |  | { | 
| 649 | 0 |  |  | 0 | 1 |  | my ($self, $time) = @_; | 
| 650 | 0 |  |  |  |  |  | my $id = ident $self; | 
| 651 |  |  |  |  |  |  |  | 
| 652 | 0 |  |  |  |  |  | $price_time{$id} = $time; | 
| 653 | 0 | 0 |  |  |  |  | $price_time_sec{$id} = str2time($time) if $CAN_PARSE_DATES; | 
| 654 |  |  |  |  |  |  |  | 
| 655 | 0 |  |  |  |  |  | $self; | 
| 656 |  |  |  |  |  |  | } | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | ############################################################################### | 
| 659 |  |  |  |  |  |  | # | 
| 660 |  |  |  |  |  |  | #   Sub Name:       set_price_time_sec | 
| 661 |  |  |  |  |  |  | # | 
| 662 |  |  |  |  |  |  | #   Description:    Set the price_time_sec value; also updates price_time. | 
| 663 |  |  |  |  |  |  | # | 
| 664 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 665 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 666 |  |  |  |  |  |  | #                   $time     in      scalar    Time, in seconds | 
| 667 |  |  |  |  |  |  | # | 
| 668 |  |  |  |  |  |  | #   Globals:        %price_time | 
| 669 |  |  |  |  |  |  | #                   %price_time_sec | 
| 670 |  |  |  |  |  |  | # | 
| 671 |  |  |  |  |  |  | #   Returns:        $self | 
| 672 |  |  |  |  |  |  | # | 
| 673 |  |  |  |  |  |  | ############################################################################### | 
| 674 |  |  |  |  |  |  | sub set_price_time_sec | 
| 675 |  |  |  |  |  |  | { | 
| 676 | 0 |  |  | 0 | 1 |  | my ($self, $time) = @_; | 
| 677 | 0 |  |  |  |  |  | my $id = ident $self; | 
| 678 |  |  |  |  |  |  |  | 
| 679 | 0 |  |  |  |  |  | $price_time_sec{$id} = $time; | 
| 680 | 0 |  |  |  |  |  | my @parts = localtime $time; | 
| 681 | 0 |  |  |  |  |  | $price_time{$id} = sprintf("%4d-%02d-%02dT%02d:%02d:%02dZ", | 
| 682 |  |  |  |  |  |  | $parts[5] + 1900, # year | 
| 683 |  |  |  |  |  |  | $parts[4] + 1,    # month | 
| 684 |  |  |  |  |  |  | $parts[3],        # day | 
| 685 |  |  |  |  |  |  | @parts[2,1,0]);   # hours, mins, secs | 
| 686 |  |  |  |  |  |  |  | 
| 687 | 0 |  |  |  |  |  | $self; | 
| 688 |  |  |  |  |  |  | } | 
| 689 |  |  |  |  |  |  |  | 
| 690 |  |  |  |  |  |  | ############################################################################### | 
| 691 |  |  |  |  |  |  | # | 
| 692 |  |  |  |  |  |  | #   Sub Name:       set_prices | 
| 693 |  |  |  |  |  |  | # | 
| 694 |  |  |  |  |  |  | #   Description:    Set new data for the price information. Checks that the | 
| 695 |  |  |  |  |  |  | #                   passed-in value is a list-ref, and that all elements are | 
| 696 |  |  |  |  |  |  | #                   hash refs. | 
| 697 |  |  |  |  |  |  | # | 
| 698 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 699 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 700 |  |  |  |  |  |  | #                   $prices   in      listref   New price data | 
| 701 |  |  |  |  |  |  | # | 
| 702 |  |  |  |  |  |  | #   Globals:        %prices | 
| 703 |  |  |  |  |  |  | # | 
| 704 |  |  |  |  |  |  | #   Returns:        Success:    $self | 
| 705 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 706 |  |  |  |  |  |  | # | 
| 707 |  |  |  |  |  |  | ############################################################################### | 
| 708 |  |  |  |  |  |  | sub set_prices | 
| 709 |  |  |  |  |  |  | { | 
| 710 | 0 |  |  | 0 | 1 |  | my ($self, $prices) = @_; | 
| 711 |  |  |  |  |  |  |  | 
| 712 | 0 | 0 |  |  |  |  | throw Error::Simple('Argument to "set_prices" must be an array reference') | 
| 713 |  |  |  |  |  |  | unless (ref($prices) eq 'ARRAY'); | 
| 714 | 0 | 0 |  |  |  |  | throw Error::Simple('All elements of the array ref to "set_prices" must ' . | 
| 715 |  |  |  |  |  |  | 'be hash references') | 
| 716 |  |  |  |  |  |  | if (grep(ref($_) ne 'HASH', @$prices)); | 
| 717 | 0 |  |  |  |  |  | $prices{ident $self} = _copy_aoh($prices); | 
| 718 |  |  |  |  |  |  |  | 
| 719 | 0 |  |  |  |  |  | $self; | 
| 720 |  |  |  |  |  |  | } | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | ############################################################################### | 
| 723 |  |  |  |  |  |  | # | 
| 724 |  |  |  |  |  |  | #   Sub Name:       set_marc | 
| 725 |  |  |  |  |  |  | # | 
| 726 |  |  |  |  |  |  | #   Description:    Set new data for the MARC information. Checks that the | 
| 727 |  |  |  |  |  |  | #                   passed-in value is a list-ref, and that all elements are | 
| 728 |  |  |  |  |  |  | #                   hash refs. | 
| 729 |  |  |  |  |  |  | # | 
| 730 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 731 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 732 |  |  |  |  |  |  | #                   $marc     in      listref   New MARC data | 
| 733 |  |  |  |  |  |  | # | 
| 734 |  |  |  |  |  |  | #   Globals:        %marc | 
| 735 |  |  |  |  |  |  | # | 
| 736 |  |  |  |  |  |  | #   Returns:        Success:    $self | 
| 737 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 738 |  |  |  |  |  |  | # | 
| 739 |  |  |  |  |  |  | ############################################################################### | 
| 740 |  |  |  |  |  |  | sub set_marc | 
| 741 |  |  |  |  |  |  | { | 
| 742 | 0 |  |  | 0 | 1 |  | my ($self, $marc) = @_; | 
| 743 |  |  |  |  |  |  |  | 
| 744 | 0 | 0 |  |  |  |  | throw Error::Simple('Argument to "set_marc" must be an array reference') | 
| 745 |  |  |  |  |  |  | unless (ref($marc) eq 'ARRAY'); | 
| 746 | 0 | 0 |  |  |  |  | throw Error::Simple('All elements of the array ref to "set_marc" must ' . | 
| 747 |  |  |  |  |  |  | 'be hash references') | 
| 748 |  |  |  |  |  |  | if (grep(ref($_) ne 'HASH', @$marc)); | 
| 749 | 0 |  |  |  |  |  | $marc{ident $self} = _copy_aoh($marc); | 
| 750 |  |  |  |  |  |  |  | 
| 751 | 0 |  |  |  |  |  | $self; | 
| 752 |  |  |  |  |  |  | } | 
| 753 |  |  |  |  |  |  |  | 
| 754 |  |  |  |  |  |  | ############################################################################### | 
| 755 |  |  |  |  |  |  | # | 
| 756 |  |  |  |  |  |  | #   Sub Name:       copy | 
| 757 |  |  |  |  |  |  | # | 
| 758 |  |  |  |  |  |  | #   Description:    Copy the Books-specific attributes over from target object | 
| 759 |  |  |  |  |  |  | #                   to caller. | 
| 760 |  |  |  |  |  |  | # | 
| 761 |  |  |  |  |  |  | #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION | 
| 762 |  |  |  |  |  |  | #                   $self     in      ref       Object | 
| 763 |  |  |  |  |  |  | #                   $target   in      ref       Object of the same class | 
| 764 |  |  |  |  |  |  | # | 
| 765 |  |  |  |  |  |  | #   Globals:        %id | 
| 766 |  |  |  |  |  |  | #                   %isbn | 
| 767 |  |  |  |  |  |  | #                   %title | 
| 768 |  |  |  |  |  |  | #                   %longtitle | 
| 769 |  |  |  |  |  |  | #                   %authors | 
| 770 |  |  |  |  |  |  | #                   %authors_text | 
| 771 |  |  |  |  |  |  | #                   %publisher | 
| 772 |  |  |  |  |  |  | #                   %publisher_text | 
| 773 |  |  |  |  |  |  | #                   %subjects | 
| 774 |  |  |  |  |  |  | #                   %dewey_decimal | 
| 775 |  |  |  |  |  |  | #                   %dewey_decimal_normalized | 
| 776 |  |  |  |  |  |  | #                   %lcc_number | 
| 777 |  |  |  |  |  |  | #                   %language | 
| 778 |  |  |  |  |  |  | #                   %physical_description_text | 
| 779 |  |  |  |  |  |  | #                   %edition_info | 
| 780 |  |  |  |  |  |  | #                   %change_time | 
| 781 |  |  |  |  |  |  | #                   %change_time_sec | 
| 782 |  |  |  |  |  |  | #                   %price_time | 
| 783 |  |  |  |  |  |  | #                   %price_time_sec | 
| 784 |  |  |  |  |  |  | #                   %summary | 
| 785 |  |  |  |  |  |  | #                   %notes | 
| 786 |  |  |  |  |  |  | #                   %urlstext | 
| 787 |  |  |  |  |  |  | #                   %awardstext | 
| 788 |  |  |  |  |  |  | #                   %prices | 
| 789 |  |  |  |  |  |  | #                   %marc | 
| 790 |  |  |  |  |  |  | # | 
| 791 |  |  |  |  |  |  | #   Returns:        Success:    void | 
| 792 |  |  |  |  |  |  | #                   Failure:    throws Error::Simple | 
| 793 |  |  |  |  |  |  | # | 
| 794 |  |  |  |  |  |  | ############################################################################### | 
| 795 |  |  |  |  |  |  | sub copy : CUMULATIVE | 
| 796 |  |  |  |  |  |  | { | 
| 797 | 0 |  |  | 0 | 1 | 0 | my ($self, $target) = @_; | 
| 798 |  |  |  |  |  |  |  | 
| 799 | 0 | 0 |  |  |  | 0 | throw Error::Simple("Argument to 'copy' must be the same class as caller") | 
| 800 |  |  |  |  |  |  | unless (ref($self) eq ref($target)); | 
| 801 |  |  |  |  |  |  |  | 
| 802 | 0 |  |  |  |  | 0 | my $id1 = ident $self; | 
| 803 | 0 |  |  |  |  | 0 | my $id2 = ident $target; | 
| 804 |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  | # Do the simple (scalar) attributes first | 
| 806 | 0 |  |  |  |  | 0 | $id{$id1}                        = $id{$id2}; | 
| 807 | 0 |  |  |  |  | 0 | $isbn{$id1}                      = $isbn{$id2}; | 
| 808 | 0 |  |  |  |  | 0 | $title{$id1}                     = $title{$id2}; | 
| 809 | 0 |  |  |  |  | 0 | $longtitle{$id1}                 = $longtitle{$id2}; | 
| 810 | 0 |  |  |  |  | 0 | $authors_text{$id1}              = $authors_text{$id2}; | 
| 811 | 0 |  |  |  |  | 0 | $publisher_text{$id1}            = $publisher_text{$id2}; | 
| 812 | 0 |  |  |  |  | 0 | $publisher{$id1}                 = $publisher{$id2}; | 
| 813 | 0 |  |  |  |  | 0 | $dewey_decimal{$id1}             = $dewey_decimal{$id2}; | 
| 814 | 0 |  |  |  |  | 0 | $dewey_decimal_normalized{$id1}  = $dewey_decimal_normalized{$id2}; | 
| 815 | 0 |  |  |  |  | 0 | $lcc_number{$id1}                = $lcc_number{$id2}; | 
| 816 | 0 |  |  |  |  | 0 | $language{$id1}                  = $language{$id2}; | 
| 817 | 0 |  |  |  |  | 0 | $physical_description_text{$id1} = $physical_description_text{$id2}; | 
| 818 | 0 |  |  |  |  | 0 | $edition_info{$id1}              = $edition_info{$id2}; | 
| 819 | 0 |  |  |  |  | 0 | $change_time{$id1}               = $change_time{$id2}; | 
| 820 | 0 |  |  |  |  | 0 | $change_time_sec{$id1}           = $change_time_sec{$id2}; | 
| 821 | 0 |  |  |  |  | 0 | $price_time{$id1}                = $price_time{$id2}; | 
| 822 | 0 |  |  |  |  | 0 | $price_time_sec{$id1}            = $price_time_sec{$id2}; | 
| 823 | 0 |  |  |  |  | 0 | $summary{$id1}                   = $summary{$id2}; | 
| 824 | 0 |  |  |  |  | 0 | $notes{$id1}                     = $notes{$id2}; | 
| 825 | 0 |  |  |  |  | 0 | $urlstext{$id1}                  = $urlstext{$id2}; | 
| 826 | 0 |  |  |  |  | 0 | $awardstext{$id1}                = $awardstext{$id2}; | 
| 827 |  |  |  |  |  |  |  | 
| 828 |  |  |  |  |  |  | # Each of these must be tested, and references copied by value | 
| 829 | 0 | 0 |  |  |  | 0 | $authors{$id1}  = [ @{$authors{$id2}}  ]   if ref($authors{$id2}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 830 | 0 | 0 |  |  |  | 0 | $subjects{$id1} = [ @{$subjects{$id2}} ]   if ref($subjects{$id2}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 831 | 0 | 0 |  |  |  | 0 | $prices{$id1}   = _copy_aoh($prices{$id2}) if ref($prices{$id2}); | 
| 832 | 0 | 0 |  |  |  | 0 | $marc{$id1}     = _copy_aoh($marc{$id2})   if ref($marc{$id2}); | 
| 833 |  |  |  |  |  |  |  | 
| 834 | 0 |  |  |  |  | 0 | return; | 
| 835 | 3 |  |  | 3 |  | 5616 | } | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 16 |  | 
| 836 |  |  |  |  |  |  |  | 
| 837 |  |  |  |  |  |  | # Copy the array-of-hashrefs and return the new | 
| 838 |  |  |  |  |  |  | sub _copy_aoh | 
| 839 |  |  |  |  |  |  | { | 
| 840 | 0 |  |  | 0 |  |  | my $list = shift; | 
| 841 |  |  |  |  |  |  |  | 
| 842 | 0 |  |  |  |  |  | my $new = []; | 
| 843 | 0 |  |  |  |  |  | for (@$list) | 
| 844 |  |  |  |  |  |  | { | 
| 845 | 0 |  |  |  |  |  | push(@$new, { %$_ }); | 
| 846 |  |  |  |  |  |  | } | 
| 847 |  |  |  |  |  |  |  | 
| 848 | 0 |  |  |  |  |  | $new; | 
| 849 |  |  |  |  |  |  | } | 
| 850 |  |  |  |  |  |  |  | 
| 851 |  |  |  |  |  |  | 1; | 
| 852 |  |  |  |  |  |  |  | 
| 853 |  |  |  |  |  |  | =pod | 
| 854 |  |  |  |  |  |  |  | 
| 855 |  |  |  |  |  |  | =head1 NAME | 
| 856 |  |  |  |  |  |  |  | 
| 857 |  |  |  |  |  |  | WebService::ISBNDB::API::Books - Data class for book information | 
| 858 |  |  |  |  |  |  |  | 
| 859 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 860 |  |  |  |  |  |  |  | 
| 861 |  |  |  |  |  |  | use WebService::ISBNDB::API::Books; | 
| 862 |  |  |  |  |  |  |  | 
| 863 |  |  |  |  |  |  | my $book = WebService::ISBNDB::API->new({ api_key => $key, | 
| 864 |  |  |  |  |  |  | isbn => '0596002068' }); | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 867 |  |  |  |  |  |  |  | 
| 868 |  |  |  |  |  |  | This class represents book data from B. It is a sub-class of | 
| 869 |  |  |  |  |  |  | B (see L), and inherits all | 
| 870 |  |  |  |  |  |  | the attributes and methods from that class. | 
| 871 |  |  |  |  |  |  |  | 
| 872 |  |  |  |  |  |  | =head1 METHODS | 
| 873 |  |  |  |  |  |  |  | 
| 874 |  |  |  |  |  |  | The following methods are specific to this class, or overridden from the | 
| 875 |  |  |  |  |  |  | super-class. | 
| 876 |  |  |  |  |  |  |  | 
| 877 |  |  |  |  |  |  | =head2 Constructor | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | The constructor for this class may take a single scalar argument in lieu of a | 
| 880 |  |  |  |  |  |  | hash reference: | 
| 881 |  |  |  |  |  |  |  | 
| 882 |  |  |  |  |  |  | =over 4 | 
| 883 |  |  |  |  |  |  |  | 
| 884 |  |  |  |  |  |  | =item new($ISBN|$TITLE|$ARGS) | 
| 885 |  |  |  |  |  |  |  | 
| 886 |  |  |  |  |  |  | This constructs a new object and returns a referent to it. If the parameter | 
| 887 |  |  |  |  |  |  | passed is a hash reference, it is handled as normal, per B | 
| 888 |  |  |  |  |  |  | mechanics. If the value is a scalar, it is tested to see if it is a valid | 
| 889 |  |  |  |  |  |  | ISBN (using the B module). If it is, it is used as a search | 
| 890 |  |  |  |  |  |  | key to find the corresponding book. If it is not a valid ISBN, it is assumed | 
| 891 |  |  |  |  |  |  | to be the title, and is likewise used as a search key. Since the title may | 
| 892 |  |  |  |  |  |  | return more than one match, the first matching record from the source is used | 
| 893 |  |  |  |  |  |  | to construct the object. | 
| 894 |  |  |  |  |  |  |  | 
| 895 |  |  |  |  |  |  | If the argument is the hash-reference form, then a new object is always | 
| 896 |  |  |  |  |  |  | constructed; to perform searches see the search() and find() methods. Thus, | 
| 897 |  |  |  |  |  |  | the following two lines are in fact different: | 
| 898 |  |  |  |  |  |  |  | 
| 899 |  |  |  |  |  |  | $book = WebService::ISBNDB::API::Books->new({ isbn => '0596002068' }); | 
| 900 |  |  |  |  |  |  |  | 
| 901 |  |  |  |  |  |  | $book = WebService::ISBNDB::API::Books->new('0596002068'); | 
| 902 |  |  |  |  |  |  |  | 
| 903 |  |  |  |  |  |  | The first creates a new object that has only the C attribute set. The | 
| 904 |  |  |  |  |  |  | second returns a new object that represents the book with ISBN C<0596002068>, | 
| 905 |  |  |  |  |  |  | with all data present. | 
| 906 |  |  |  |  |  |  |  | 
| 907 |  |  |  |  |  |  | =back | 
| 908 |  |  |  |  |  |  |  | 
| 909 |  |  |  |  |  |  | The class also defines: | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | =over 4 | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | =item copy($TARGET) | 
| 914 |  |  |  |  |  |  |  | 
| 915 |  |  |  |  |  |  | Copies the target object into the calling object. All attributes (including | 
| 916 |  |  |  |  |  |  | the ID) are copied. This method is marked "CUMULATIVE" (see L), | 
| 917 |  |  |  |  |  |  | and any sub-class of this class should provide their own copy() and also mark | 
| 918 |  |  |  |  |  |  | it "CUMULATIVE", to ensure that all attributes at all levels are copied. | 
| 919 |  |  |  |  |  |  |  | 
| 920 |  |  |  |  |  |  | =back | 
| 921 |  |  |  |  |  |  |  | 
| 922 |  |  |  |  |  |  | See the copy() method in L. | 
| 923 |  |  |  |  |  |  |  | 
| 924 |  |  |  |  |  |  | =head2 Accessors | 
| 925 |  |  |  |  |  |  |  | 
| 926 |  |  |  |  |  |  | The following attributes are used to maintain the content of a book object: | 
| 927 |  |  |  |  |  |  |  | 
| 928 |  |  |  |  |  |  | =over 4 | 
| 929 |  |  |  |  |  |  |  | 
| 930 |  |  |  |  |  |  | =item id | 
| 931 |  |  |  |  |  |  |  | 
| 932 |  |  |  |  |  |  | The unique ID within the B system for this book. | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  | =item isbn | 
| 935 |  |  |  |  |  |  |  | 
| 936 |  |  |  |  |  |  | The ISBN (International Standard Book Number) for the book (without hyphens). | 
| 937 |  |  |  |  |  |  |  | 
| 938 |  |  |  |  |  |  | =item title | 
| 939 |  |  |  |  |  |  |  | 
| 940 |  |  |  |  |  |  | The title of the book. | 
| 941 |  |  |  |  |  |  |  | 
| 942 |  |  |  |  |  |  | =item longtitle | 
| 943 |  |  |  |  |  |  |  | 
| 944 |  |  |  |  |  |  | The full title of the book, including any sub-title. | 
| 945 |  |  |  |  |  |  |  | 
| 946 |  |  |  |  |  |  | =item authors | 
| 947 |  |  |  |  |  |  |  | 
| 948 |  |  |  |  |  |  | An array (stored as a reference) of the B | 
| 949 |  |  |  |  |  |  | objects that refer to the authors of the book. These are not actually loaded | 
| 950 |  |  |  |  |  |  | from the service until they are first fetched. | 
| 951 |  |  |  |  |  |  |  | 
| 952 |  |  |  |  |  |  | =item authors_text | 
| 953 |  |  |  |  |  |  |  | 
| 954 |  |  |  |  |  |  | A simple textual representation of the authors, as returned by the service. | 
| 955 |  |  |  |  |  |  | This may be more convenient to use than the author objects, if you only want | 
| 956 |  |  |  |  |  |  | to display the names themselves. | 
| 957 |  |  |  |  |  |  |  | 
| 958 |  |  |  |  |  |  | =item publisher | 
| 959 |  |  |  |  |  |  |  | 
| 960 |  |  |  |  |  |  | The B object that refers to the book's | 
| 961 |  |  |  |  |  |  | publisher.  This is not loaded until the first request to fetch it is made. | 
| 962 |  |  |  |  |  |  |  | 
| 963 |  |  |  |  |  |  | =item publisher_text | 
| 964 |  |  |  |  |  |  |  | 
| 965 |  |  |  |  |  |  | A simple textual representation of the publisher, as returned by the service. | 
| 966 |  |  |  |  |  |  | This may be more convenient to use than the object, if you only wish to | 
| 967 |  |  |  |  |  |  | display the publisher's name. | 
| 968 |  |  |  |  |  |  |  | 
| 969 |  |  |  |  |  |  | =item subjects | 
| 970 |  |  |  |  |  |  |  | 
| 971 |  |  |  |  |  |  | An array (stored as a reference) of the B | 
| 972 |  |  |  |  |  |  | objects that refer to the subjects this book is associated with. As with the | 
| 973 |  |  |  |  |  |  | authors, the actual objects are not loaded until requested. | 
| 974 |  |  |  |  |  |  |  | 
| 975 |  |  |  |  |  |  | =item dewey_decimal | 
| 976 |  |  |  |  |  |  |  | 
| 977 |  |  |  |  |  |  | The book's Dewey Decimal classification number. | 
| 978 |  |  |  |  |  |  |  | 
| 979 |  |  |  |  |  |  | =item dewey_decimal_normalized | 
| 980 |  |  |  |  |  |  |  | 
| 981 |  |  |  |  |  |  | The normalized form of the Dewey Decimal number for the book. | 
| 982 |  |  |  |  |  |  |  | 
| 983 |  |  |  |  |  |  | =item lcc_number | 
| 984 |  |  |  |  |  |  |  | 
| 985 |  |  |  |  |  |  | The Library of Congress Classification number for the book. | 
| 986 |  |  |  |  |  |  |  | 
| 987 |  |  |  |  |  |  | =item language | 
| 988 |  |  |  |  |  |  |  | 
| 989 |  |  |  |  |  |  | The language the book is printed in. The form and content of this field may | 
| 990 |  |  |  |  |  |  | not be standardized. | 
| 991 |  |  |  |  |  |  |  | 
| 992 |  |  |  |  |  |  | =item physical_description_text | 
| 993 |  |  |  |  |  |  |  | 
| 994 |  |  |  |  |  |  | Text describing the physical dimensions of the book. | 
| 995 |  |  |  |  |  |  |  | 
| 996 |  |  |  |  |  |  | =item edition_info | 
| 997 |  |  |  |  |  |  |  | 
| 998 |  |  |  |  |  |  | Any additional information on the particular edition of the book. | 
| 999 |  |  |  |  |  |  |  | 
| 1000 |  |  |  |  |  |  | =item change_time | 
| 1001 |  |  |  |  |  |  |  | 
| 1002 |  |  |  |  |  |  | A string representation of the time when this record was last changed. The | 
| 1003 |  |  |  |  |  |  | string is in ISO 8601 form, with no explicit time-zone specified. UTC time | 
| 1004 |  |  |  |  |  |  | is assumed in internal manipulations. | 
| 1005 |  |  |  |  |  |  |  | 
| 1006 |  |  |  |  |  |  | =item change_time_sec | 
| 1007 |  |  |  |  |  |  |  | 
| 1008 |  |  |  |  |  |  | If the B module is available, this attribute will hold the value | 
| 1009 |  |  |  |  |  |  | from C, converted to seconds since the UNIX Epoch. Otherwise, | 
| 1010 |  |  |  |  |  |  | this attribute will always be C. | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 |  |  |  |  |  |  | =item price_time | 
| 1013 |  |  |  |  |  |  |  | 
| 1014 |  |  |  |  |  |  | A string representation of the time when the price information for this | 
| 1015 |  |  |  |  |  |  | record was last updated. As above, the string is in ISO 8601 format with no | 
| 1016 |  |  |  |  |  |  | time-zone, and it assumed to be UTC internally. | 
| 1017 |  |  |  |  |  |  |  | 
| 1018 |  |  |  |  |  |  | =item price_time_sec | 
| 1019 |  |  |  |  |  |  |  | 
| 1020 |  |  |  |  |  |  | As with C, only for the price-change value. Requires the | 
| 1021 |  |  |  |  |  |  | availability of B, or else the value will always be C. | 
| 1022 |  |  |  |  |  |  |  | 
| 1023 |  |  |  |  |  |  | =item summary | 
| 1024 |  |  |  |  |  |  |  | 
| 1025 |  |  |  |  |  |  | The content of the CSummaryE> tag, which is free-form text. The | 
| 1026 |  |  |  |  |  |  | text has leading and trailing white-space removed, and all new-lines | 
| 1027 |  |  |  |  |  |  | converted to spaces, to yield a single-line string value. | 
| 1028 |  |  |  |  |  |  |  | 
| 1029 |  |  |  |  |  |  | =item notes | 
| 1030 |  |  |  |  |  |  |  | 
| 1031 |  |  |  |  |  |  | Another free-form text field, similar to C, but less used. | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 |  |  |  |  |  |  | =item urlstext | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  | Fairly free-form text, used to specify URLs related to the book. | 
| 1036 |  |  |  |  |  |  |  | 
| 1037 |  |  |  |  |  |  | =item awardstext | 
| 1038 |  |  |  |  |  |  |  | 
| 1039 |  |  |  |  |  |  | More free-form text, this to specify any awards the book has received. | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 |  |  |  |  |  |  | =item prices | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  | If price information is available for the book, this attribute will contain | 
| 1044 |  |  |  |  |  |  | a list-reference containing zero or more hash references. Each hash reference | 
| 1045 |  |  |  |  |  |  | will have the following keys (all will be present on every hash reference, but | 
| 1046 |  |  |  |  |  |  | some may be empty or C): | 
| 1047 |  |  |  |  |  |  |  | 
| 1048 |  |  |  |  |  |  | =over 8 | 
| 1049 |  |  |  |  |  |  |  | 
| 1050 |  |  |  |  |  |  | =item store_isbn | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 |  |  |  |  |  |  | The ISBN for the book at the store, if different from the book's regular | 
| 1053 |  |  |  |  |  |  | ISBN. Not set if the two are the same. | 
| 1054 |  |  |  |  |  |  |  | 
| 1055 |  |  |  |  |  |  | =item store_title | 
| 1056 |  |  |  |  |  |  |  | 
| 1057 |  |  |  |  |  |  | The book's title at the store, if different from the book's regular title. | 
| 1058 |  |  |  |  |  |  | Not usually set if the two are the same. | 
| 1059 |  |  |  |  |  |  |  | 
| 1060 |  |  |  |  |  |  | =item store_url | 
| 1061 |  |  |  |  |  |  |  | 
| 1062 |  |  |  |  |  |  | URL for the book. This may be a relative URL, in which case it is relative to | 
| 1063 |  |  |  |  |  |  | the store's website. If it is an absolute URL (complete URL), it is a | 
| 1064 |  |  |  |  |  |  | redirector URL originating at B. The URL is used for purchasing | 
| 1065 |  |  |  |  |  |  | the book, and the redirect URLs allow B to collect small | 
| 1066 |  |  |  |  |  |  | commissions off of sales they facilitate, which in turn helps to keep their | 
| 1067 |  |  |  |  |  |  | service available and free. | 
| 1068 |  |  |  |  |  |  |  | 
| 1069 |  |  |  |  |  |  | =item store_id | 
| 1070 |  |  |  |  |  |  |  | 
| 1071 |  |  |  |  |  |  | Unique identifier for the store. | 
| 1072 |  |  |  |  |  |  |  | 
| 1073 |  |  |  |  |  |  | =item currency_code | 
| 1074 |  |  |  |  |  |  |  | 
| 1075 |  |  |  |  |  |  | The code for the currency the price is expressed in. | 
| 1076 |  |  |  |  |  |  |  | 
| 1077 |  |  |  |  |  |  | =item is_in_stock | 
| 1078 |  |  |  |  |  |  |  | 
| 1079 |  |  |  |  |  |  | A boolean value indicating whether the book is in stock. | 
| 1080 |  |  |  |  |  |  |  | 
| 1081 |  |  |  |  |  |  | =item is_historic | 
| 1082 |  |  |  |  |  |  |  | 
| 1083 |  |  |  |  |  |  | A boolean value indicating whether the price this record describes is | 
| 1084 |  |  |  |  |  |  | considered "historic". Any price older than 24 hours should generally be | 
| 1085 |  |  |  |  |  |  | considered historic, even if this value is true. | 
| 1086 |  |  |  |  |  |  |  | 
| 1087 |  |  |  |  |  |  | =item is_new | 
| 1088 |  |  |  |  |  |  |  | 
| 1089 |  |  |  |  |  |  | A boolean value indicating whether the book offered is new or used. | 
| 1090 |  |  |  |  |  |  |  | 
| 1091 |  |  |  |  |  |  | =item currency_rate | 
| 1092 |  |  |  |  |  |  |  | 
| 1093 |  |  |  |  |  |  | Currency rate against the US dollar, only set if the C is not | 
| 1094 |  |  |  |  |  |  | C. | 
| 1095 |  |  |  |  |  |  |  | 
| 1096 |  |  |  |  |  |  | =item price | 
| 1097 |  |  |  |  |  |  |  | 
| 1098 |  |  |  |  |  |  | The price of the book (expressed in the currency indicated by C, | 
| 1099 |  |  |  |  |  |  | above). | 
| 1100 |  |  |  |  |  |  |  | 
| 1101 |  |  |  |  |  |  | =item check_time | 
| 1102 |  |  |  |  |  |  |  | 
| 1103 |  |  |  |  |  |  | String representation of the time when this price was last checked. As with | 
| 1104 |  |  |  |  |  |  | the other time-oriented values, this is in ISO 8601 format with no explicit | 
| 1105 |  |  |  |  |  |  | time-zone. | 
| 1106 |  |  |  |  |  |  |  | 
| 1107 |  |  |  |  |  |  | =item check_time_sec | 
| 1108 |  |  |  |  |  |  |  | 
| 1109 |  |  |  |  |  |  | If the B package is available, this is the value of C | 
| 1110 |  |  |  |  |  |  | expressed in seconds, suitable for use with the Perl B keyword. | 
| 1111 |  |  |  |  |  |  |  | 
| 1112 |  |  |  |  |  |  | =back | 
| 1113 |  |  |  |  |  |  |  | 
| 1114 |  |  |  |  |  |  | =item marc | 
| 1115 |  |  |  |  |  |  |  | 
| 1116 |  |  |  |  |  |  | If MARC information is available for the book, this attribute will contain | 
| 1117 |  |  |  |  |  |  | a list-reference containing zero or more hash references. Each hash reference | 
| 1118 |  |  |  |  |  |  | will have the following keys (all will be present on every hash reference, but | 
| 1119 |  |  |  |  |  |  | some may be empty or C): | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  | =over 8 | 
| 1122 |  |  |  |  |  |  |  | 
| 1123 |  |  |  |  |  |  | =item library_name | 
| 1124 |  |  |  |  |  |  |  | 
| 1125 |  |  |  |  |  |  | Name of the library this record is taken from. | 
| 1126 |  |  |  |  |  |  |  | 
| 1127 |  |  |  |  |  |  | =item last_update | 
| 1128 |  |  |  |  |  |  |  | 
| 1129 |  |  |  |  |  |  | ISO 8601 string representing the last time the record was updated from the | 
| 1130 |  |  |  |  |  |  | library. | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 |  |  |  |  |  |  | =item last_update_sec | 
| 1133 |  |  |  |  |  |  |  | 
| 1134 |  |  |  |  |  |  | If B is available, this will be the C attribute | 
| 1135 |  |  |  |  |  |  | converted to seconds, measured from the UNIX epoch. | 
| 1136 |  |  |  |  |  |  |  | 
| 1137 |  |  |  |  |  |  | =item marc_url | 
| 1138 |  |  |  |  |  |  |  | 
| 1139 |  |  |  |  |  |  | The URL to the MARC record on the library's site. | 
| 1140 |  |  |  |  |  |  |  | 
| 1141 |  |  |  |  |  |  | =back | 
| 1142 |  |  |  |  |  |  |  | 
| 1143 |  |  |  |  |  |  | =back | 
| 1144 |  |  |  |  |  |  |  | 
| 1145 |  |  |  |  |  |  | The following accessors are provided to manage these attributes: | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 |  |  |  |  |  |  | =over 4 | 
| 1148 |  |  |  |  |  |  |  | 
| 1149 |  |  |  |  |  |  | =item get_id | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | Return the book ID. | 
| 1152 |  |  |  |  |  |  |  | 
| 1153 |  |  |  |  |  |  | =item set_id($ID) | 
| 1154 |  |  |  |  |  |  |  | 
| 1155 |  |  |  |  |  |  | Sets the book ID. This method is restricted to this class, and cannot be | 
| 1156 |  |  |  |  |  |  | called outside of it. In general, you shouldn't need to set the ID after the | 
| 1157 |  |  |  |  |  |  | object is created, since B is a read-only source. | 
| 1158 |  |  |  |  |  |  |  | 
| 1159 |  |  |  |  |  |  | =item get_isbn | 
| 1160 |  |  |  |  |  |  |  | 
| 1161 |  |  |  |  |  |  | Return the ISBN of the book. In general, the ISBN has had any hyphens removed. | 
| 1162 |  |  |  |  |  |  |  | 
| 1163 |  |  |  |  |  |  | =item set_isbn($ISBN) | 
| 1164 |  |  |  |  |  |  |  | 
| 1165 |  |  |  |  |  |  | Set the book ISBN. The value is tested with B to ensure that | 
| 1166 |  |  |  |  |  |  | the value is a valid ISBN. | 
| 1167 |  |  |  |  |  |  |  | 
| 1168 |  |  |  |  |  |  | =item get_title | 
| 1169 |  |  |  |  |  |  |  | 
| 1170 |  |  |  |  |  |  | Return the common title of the book. | 
| 1171 |  |  |  |  |  |  |  | 
| 1172 |  |  |  |  |  |  | =item set_title($TITLE) | 
| 1173 |  |  |  |  |  |  |  | 
| 1174 |  |  |  |  |  |  | Set the title of the book. | 
| 1175 |  |  |  |  |  |  |  | 
| 1176 |  |  |  |  |  |  | =item get_longtitle | 
| 1177 |  |  |  |  |  |  |  | 
| 1178 |  |  |  |  |  |  | Return the long title of the book. This will include subtitles, for example. | 
| 1179 |  |  |  |  |  |  |  | 
| 1180 |  |  |  |  |  |  | =item set_longtitle($LONGTITLE) | 
| 1181 |  |  |  |  |  |  |  | 
| 1182 |  |  |  |  |  |  | Set the long title of the book. | 
| 1183 |  |  |  |  |  |  |  | 
| 1184 |  |  |  |  |  |  | =item get_authors | 
| 1185 |  |  |  |  |  |  |  | 
| 1186 |  |  |  |  |  |  | Get the list of author objects (instances of | 
| 1187 |  |  |  |  |  |  | B or a sub-class) for the book. The objects | 
| 1188 |  |  |  |  |  |  | are not fetched from the source until the first call to this method. | 
| 1189 |  |  |  |  |  |  |  | 
| 1190 |  |  |  |  |  |  | =item set_authors($LIST) | 
| 1191 |  |  |  |  |  |  |  | 
| 1192 |  |  |  |  |  |  | Set the list of authors for this book. The value must be a list-reference. If | 
| 1193 |  |  |  |  |  |  | the values in the list reference are strings instead of objects, then the | 
| 1194 |  |  |  |  |  |  | first call to get_authors() will convert them into objects. The strings must | 
| 1195 |  |  |  |  |  |  | be the author ID values as returned by the service. | 
| 1196 |  |  |  |  |  |  |  | 
| 1197 |  |  |  |  |  |  | =item get_authors_text | 
| 1198 |  |  |  |  |  |  |  | 
| 1199 |  |  |  |  |  |  | Return the text-representation of the authors, as returned by the service. | 
| 1200 |  |  |  |  |  |  |  | 
| 1201 |  |  |  |  |  |  | =item set_authors_text($TEXT) | 
| 1202 |  |  |  |  |  |  |  | 
| 1203 |  |  |  |  |  |  | Set the text-representation of the authors. | 
| 1204 |  |  |  |  |  |  |  | 
| 1205 |  |  |  |  |  |  | =item get_publisher | 
| 1206 |  |  |  |  |  |  |  | 
| 1207 |  |  |  |  |  |  | Return the publisher object (instance of | 
| 1208 |  |  |  |  |  |  | B or a sub-class) for this book. The | 
| 1209 |  |  |  |  |  |  | object is not loaded from the source until the first request to this method. | 
| 1210 |  |  |  |  |  |  |  | 
| 1211 |  |  |  |  |  |  | =item set_publisher($PUBLISHER) | 
| 1212 |  |  |  |  |  |  |  | 
| 1213 |  |  |  |  |  |  | Set the publisher for this book. The value should be either a publisher object | 
| 1214 |  |  |  |  |  |  | or a string containing the publisher ID. If the ID is set as the value, the | 
| 1215 |  |  |  |  |  |  | next call to get_publisher() will resolve it into an object. | 
| 1216 |  |  |  |  |  |  |  | 
| 1217 |  |  |  |  |  |  | =item get_subjects | 
| 1218 |  |  |  |  |  |  |  | 
| 1219 |  |  |  |  |  |  | Get the list of subject objects (instances of | 
| 1220 |  |  |  |  |  |  | B or a sub-class) for the book. The objects | 
| 1221 |  |  |  |  |  |  | are not fetched from the source until the first call to this method. | 
| 1222 |  |  |  |  |  |  |  | 
| 1223 |  |  |  |  |  |  | =item set_subjects($LIST) | 
| 1224 |  |  |  |  |  |  |  | 
| 1225 |  |  |  |  |  |  | Set the list of subjects. The value must be a list-reference, and may contain | 
| 1226 |  |  |  |  |  |  | either the objects themselves or the subject ID values as returned by the | 
| 1227 |  |  |  |  |  |  | source. If the content is the ID values, then the next call to get_subjects() | 
| 1228 |  |  |  |  |  |  | will resolve them to objects. | 
| 1229 |  |  |  |  |  |  |  | 
| 1230 |  |  |  |  |  |  | =item get_dewey_decimal | 
| 1231 |  |  |  |  |  |  |  | 
| 1232 |  |  |  |  |  |  | Get the Dewey Decimal number. | 
| 1233 |  |  |  |  |  |  |  | 
| 1234 |  |  |  |  |  |  | =item set_dewey_decimal($DEWEY) | 
| 1235 |  |  |  |  |  |  |  | 
| 1236 |  |  |  |  |  |  | Set the Dewey Decimal number. | 
| 1237 |  |  |  |  |  |  |  | 
| 1238 |  |  |  |  |  |  | =item get_dewey_decimal_normalized | 
| 1239 |  |  |  |  |  |  |  | 
| 1240 |  |  |  |  |  |  | Get the normalized Dewey Decimal number. | 
| 1241 |  |  |  |  |  |  |  | 
| 1242 |  |  |  |  |  |  | =item set_dewey_decimal_normalized($DEWEY_NORM) | 
| 1243 |  |  |  |  |  |  |  | 
| 1244 |  |  |  |  |  |  | Set the normalized Dewey Decimal number. | 
| 1245 |  |  |  |  |  |  |  | 
| 1246 |  |  |  |  |  |  | =item get_lcc_number | 
| 1247 |  |  |  |  |  |  |  | 
| 1248 |  |  |  |  |  |  | Get the Library of Congress Classification number. | 
| 1249 |  |  |  |  |  |  |  | 
| 1250 |  |  |  |  |  |  | =item set_lcc_number($LCC) | 
| 1251 |  |  |  |  |  |  |  | 
| 1252 |  |  |  |  |  |  | Set the Library of Congress Classification number. | 
| 1253 |  |  |  |  |  |  |  | 
| 1254 |  |  |  |  |  |  | =item get_language | 
| 1255 |  |  |  |  |  |  |  | 
| 1256 |  |  |  |  |  |  | Get the language code for the book's text. | 
| 1257 |  |  |  |  |  |  |  | 
| 1258 |  |  |  |  |  |  | =item set_language($LANG) | 
| 1259 |  |  |  |  |  |  |  | 
| 1260 |  |  |  |  |  |  | Set the language code. | 
| 1261 |  |  |  |  |  |  |  | 
| 1262 |  |  |  |  |  |  | =item get_physical_description_text | 
| 1263 |  |  |  |  |  |  |  | 
| 1264 |  |  |  |  |  |  | Get the book's physical description text. | 
| 1265 |  |  |  |  |  |  |  | 
| 1266 |  |  |  |  |  |  | =item set_physical_description_text($PHYS) | 
| 1267 |  |  |  |  |  |  |  | 
| 1268 |  |  |  |  |  |  | Set the book's physical description text. | 
| 1269 |  |  |  |  |  |  |  | 
| 1270 |  |  |  |  |  |  | =item get_edition_info | 
| 1271 |  |  |  |  |  |  |  | 
| 1272 |  |  |  |  |  |  | Get any information on the specific edition of the book. | 
| 1273 |  |  |  |  |  |  |  | 
| 1274 |  |  |  |  |  |  | =item set_edition_info($INFO) | 
| 1275 |  |  |  |  |  |  |  | 
| 1276 |  |  |  |  |  |  | Set the edition information for the book. | 
| 1277 |  |  |  |  |  |  |  | 
| 1278 |  |  |  |  |  |  | =item get_change_time | 
| 1279 |  |  |  |  |  |  |  | 
| 1280 |  |  |  |  |  |  | Get the change-time of the book record (an ISO 8601 string, no explicit | 
| 1281 |  |  |  |  |  |  | time-zone, presumed to be UTC). | 
| 1282 |  |  |  |  |  |  |  | 
| 1283 |  |  |  |  |  |  | =item set_change_time($TIME) | 
| 1284 |  |  |  |  |  |  |  | 
| 1285 |  |  |  |  |  |  | Sets the change-time of the book record. If B is available, and | 
| 1286 |  |  |  |  |  |  | the value passed in C<$TIME> is parsable, then the C | 
| 1287 |  |  |  |  |  |  | attribute will also be updated with the equivalent value. | 
| 1288 |  |  |  |  |  |  |  | 
| 1289 |  |  |  |  |  |  | =item get_change_time_sec | 
| 1290 |  |  |  |  |  |  |  | 
| 1291 |  |  |  |  |  |  | Get the change-time as a number of seconds since the Epoch (as defined in | 
| 1292 |  |  |  |  |  |  | UNIX terms, see L). This attribute is only set if the | 
| 1293 |  |  |  |  |  |  | B module is available. | 
| 1294 |  |  |  |  |  |  |  | 
| 1295 |  |  |  |  |  |  | =item set_change_time_sec($TIME) | 
| 1296 |  |  |  |  |  |  |  | 
| 1297 |  |  |  |  |  |  | Set the seconds-since-Epoch representation of the change-time to the new | 
| 1298 |  |  |  |  |  |  | value. This will also update the C attribute, setting it to an | 
| 1299 |  |  |  |  |  |  | ISO 8601-style string that is the textual representation of C<$TIME>. | 
| 1300 |  |  |  |  |  |  |  | 
| 1301 |  |  |  |  |  |  | =item get_price_time | 
| 1302 |  |  |  |  |  |  |  | 
| 1303 |  |  |  |  |  |  | =item set_price_time($TIME) | 
| 1304 |  |  |  |  |  |  |  | 
| 1305 |  |  |  |  |  |  | =item get_price_time_sec | 
| 1306 |  |  |  |  |  |  |  | 
| 1307 |  |  |  |  |  |  | =item set_price_time_sec($TIME) | 
| 1308 |  |  |  |  |  |  |  | 
| 1309 |  |  |  |  |  |  | These are identical to the previous four, only they apply to the time-stamp | 
| 1310 |  |  |  |  |  |  | marking when the price information was last updated. The same restrictions | 
| 1311 |  |  |  |  |  |  | apply to the C attribute (B is required for it | 
| 1312 |  |  |  |  |  |  | to be set when data is read from the source). | 
| 1313 |  |  |  |  |  |  |  | 
| 1314 |  |  |  |  |  |  | =item get_summary | 
| 1315 |  |  |  |  |  |  |  | 
| 1316 |  |  |  |  |  |  | Get the summary text for this book. The summary is free-form text that has | 
| 1317 |  |  |  |  |  |  | has leading and trailing white-space removed, as well as having any internal | 
| 1318 |  |  |  |  |  |  | new-lines or tabs converted to single spaces. | 
| 1319 |  |  |  |  |  |  |  | 
| 1320 |  |  |  |  |  |  | =item set_summary($SUMMARY) | 
| 1321 |  |  |  |  |  |  |  | 
| 1322 |  |  |  |  |  |  | Set the summary text to the new content in C<$SUMMARY>. | 
| 1323 |  |  |  |  |  |  |  | 
| 1324 |  |  |  |  |  |  | =item get_notes | 
| 1325 |  |  |  |  |  |  |  | 
| 1326 |  |  |  |  |  |  | Get the notes for the book. The notes are also free-form text, and are | 
| 1327 |  |  |  |  |  |  | trimmed in the same fashion as C. | 
| 1328 |  |  |  |  |  |  |  | 
| 1329 |  |  |  |  |  |  | =item set_notes($NOTES) | 
| 1330 |  |  |  |  |  |  |  | 
| 1331 |  |  |  |  |  |  | Set the notes text for the book. | 
| 1332 |  |  |  |  |  |  |  | 
| 1333 |  |  |  |  |  |  | =item get_urlstext | 
| 1334 |  |  |  |  |  |  |  | 
| 1335 |  |  |  |  |  |  | Get the C attribute. This text should provide URLs related to | 
| 1336 |  |  |  |  |  |  | the book, when present. | 
| 1337 |  |  |  |  |  |  |  | 
| 1338 |  |  |  |  |  |  | =item set_urlstext($URLS) | 
| 1339 |  |  |  |  |  |  |  | 
| 1340 |  |  |  |  |  |  | Set the C attribute to the new value. | 
| 1341 |  |  |  |  |  |  |  | 
| 1342 |  |  |  |  |  |  | =item get_awardstext | 
| 1343 |  |  |  |  |  |  |  | 
| 1344 |  |  |  |  |  |  | Get the awards-text data for the book. If present, this should refer to any | 
| 1345 |  |  |  |  |  |  | awards the book has won. | 
| 1346 |  |  |  |  |  |  |  | 
| 1347 |  |  |  |  |  |  | =item set_awardstext($AWARDS) | 
| 1348 |  |  |  |  |  |  |  | 
| 1349 |  |  |  |  |  |  | Set the awards-text to the new data given. | 
| 1350 |  |  |  |  |  |  |  | 
| 1351 |  |  |  |  |  |  | =item get_prices | 
| 1352 |  |  |  |  |  |  |  | 
| 1353 |  |  |  |  |  |  | Get the price data for the book. This comes in the form of a list-reference | 
| 1354 |  |  |  |  |  |  | of hash-references (see earlier description of the keys). | 
| 1355 |  |  |  |  |  |  |  | 
| 1356 |  |  |  |  |  |  | =item set_prices($PRICELIST) | 
| 1357 |  |  |  |  |  |  |  | 
| 1358 |  |  |  |  |  |  | Set the price data. The value passed in must be a list reference, and every | 
| 1359 |  |  |  |  |  |  | element in the list mush be a hash reference. Otherwise an exception will be | 
| 1360 |  |  |  |  |  |  | thrown. | 
| 1361 |  |  |  |  |  |  |  | 
| 1362 |  |  |  |  |  |  | =item get_marc | 
| 1363 |  |  |  |  |  |  |  | 
| 1364 |  |  |  |  |  |  | Get the MARC data for the book. MARC data comes in the form of a | 
| 1365 |  |  |  |  |  |  | list-reference of hash-references (see above for description of the keys). | 
| 1366 |  |  |  |  |  |  |  | 
| 1367 |  |  |  |  |  |  | =item set_marc($MARCLIST) | 
| 1368 |  |  |  |  |  |  |  | 
| 1369 |  |  |  |  |  |  | Set the MARC data. The value passed in must be a list reference, and every | 
| 1370 |  |  |  |  |  |  | element in the list mush be a hash reference. Otherwise an exception will be | 
| 1371 |  |  |  |  |  |  | thrown. | 
| 1372 |  |  |  |  |  |  |  | 
| 1373 |  |  |  |  |  |  | =back | 
| 1374 |  |  |  |  |  |  |  | 
| 1375 |  |  |  |  |  |  | =head2 Utility Methods | 
| 1376 |  |  |  |  |  |  |  | 
| 1377 |  |  |  |  |  |  | Besides the constructor and the accessors, the following methods are provided | 
| 1378 |  |  |  |  |  |  | for utility: | 
| 1379 |  |  |  |  |  |  |  | 
| 1380 |  |  |  |  |  |  | =over 4 | 
| 1381 |  |  |  |  |  |  |  | 
| 1382 |  |  |  |  |  |  | =item find($ARG|$ARGS) | 
| 1383 |  |  |  |  |  |  |  | 
| 1384 |  |  |  |  |  |  | This is a specialization of find() from the parent class. It allows the | 
| 1385 |  |  |  |  |  |  | argument passed in to be a scalar in place of the usual hash reference. If the | 
| 1386 |  |  |  |  |  |  | value is a scalar, it is tested to see if it is a valid ISBN, and if so the | 
| 1387 |  |  |  |  |  |  | search is made against the ISBN with that value. If the scalar value is not a | 
| 1388 |  |  |  |  |  |  | valid ISBN, the search is made against the title instead. If the value is a | 
| 1389 |  |  |  |  |  |  | hash reference, it is passed to the super-class method. | 
| 1390 |  |  |  |  |  |  |  | 
| 1391 |  |  |  |  |  |  | =item normalize_args($ARGS) | 
| 1392 |  |  |  |  |  |  |  | 
| 1393 |  |  |  |  |  |  | This method maps the user-visible arguments as defined for find() and search() | 
| 1394 |  |  |  |  |  |  | into the actual arguments that must be passed to the service itself. In | 
| 1395 |  |  |  |  |  |  | addition, some arguments are added to the request to make the service return | 
| 1396 |  |  |  |  |  |  | extra data used for retrieving subjects, publisher information, etc. The | 
| 1397 |  |  |  |  |  |  | method changes C<$ARGS> in place, and also returns C<$ARGS> as the value from | 
| 1398 |  |  |  |  |  |  | the method. | 
| 1399 |  |  |  |  |  |  |  | 
| 1400 |  |  |  |  |  |  | =back | 
| 1401 |  |  |  |  |  |  |  | 
| 1402 |  |  |  |  |  |  | See the next section for an explanation of the available keys for searches. | 
| 1403 |  |  |  |  |  |  |  | 
| 1404 |  |  |  |  |  |  | =head1 SEARCHING | 
| 1405 |  |  |  |  |  |  |  | 
| 1406 |  |  |  |  |  |  | Both find() and search() allow the user to look up data in the B | 
| 1407 |  |  |  |  |  |  | database. The allowable search fields are limited to a certain set, however. | 
| 1408 |  |  |  |  |  |  | When either of find() or search() are called, the argument to the method | 
| 1409 |  |  |  |  |  |  | should be a hash reference of key/value pairs to be passed as arguments for | 
| 1410 |  |  |  |  |  |  | the search (the exception being that find() can accept a single string, which | 
| 1411 |  |  |  |  |  |  | has special meaning as detailed earlier). | 
| 1412 |  |  |  |  |  |  |  | 
| 1413 |  |  |  |  |  |  | Searches in the text fields are done in a case-insensitive manner. | 
| 1414 |  |  |  |  |  |  |  | 
| 1415 |  |  |  |  |  |  | The available search keys are: | 
| 1416 |  |  |  |  |  |  |  | 
| 1417 |  |  |  |  |  |  | =over 4 | 
| 1418 |  |  |  |  |  |  |  | 
| 1419 |  |  |  |  |  |  | =item title | 
| 1420 |  |  |  |  |  |  |  | 
| 1421 |  |  |  |  |  |  | The value should be a text string. The search returns books whose title | 
| 1422 |  |  |  |  |  |  | matches the string. | 
| 1423 |  |  |  |  |  |  |  | 
| 1424 |  |  |  |  |  |  | =item isbn | 
| 1425 |  |  |  |  |  |  |  | 
| 1426 |  |  |  |  |  |  | The value should be a text string. The search returns the book whose ISBN | 
| 1427 |  |  |  |  |  |  | matches the string. The string is not checked for validity, so a bad ISBN | 
| 1428 |  |  |  |  |  |  | will simply not return any records. | 
| 1429 |  |  |  |  |  |  |  | 
| 1430 |  |  |  |  |  |  | =item author | 
| 1431 |  |  |  |  |  |  |  | 
| 1432 |  |  |  |  |  |  | The value for this key should be either an object of the | 
| 1433 |  |  |  |  |  |  | B class (or sub-class thereof), or a text | 
| 1434 |  |  |  |  |  |  | string.  If the value is an object, the search is done against the specific | 
| 1435 |  |  |  |  |  |  | author ID.  If the value is a string, the search is done using the "combined" | 
| 1436 |  |  |  |  |  |  | search key, and may return results unrelated to the intended query. | 
| 1437 |  |  |  |  |  |  |  | 
| 1438 |  |  |  |  |  |  | =item publisher | 
| 1439 |  |  |  |  |  |  |  | 
| 1440 |  |  |  |  |  |  | The value for this key may be an object of the | 
| 1441 |  |  |  |  |  |  | B class (or sub-class thereof) or a text | 
| 1442 |  |  |  |  |  |  | string. If it is an object, the ID is used in a specific search. If the value | 
| 1443 |  |  |  |  |  |  | is a string, it is used with the "combined" search-key, and may return | 
| 1444 |  |  |  |  |  |  | unexpected results. | 
| 1445 |  |  |  |  |  |  |  | 
| 1446 |  |  |  |  |  |  | =item subject | 
| 1447 |  |  |  |  |  |  |  | 
| 1448 |  |  |  |  |  |  | The value for this key is expected to be either an object (of the | 
| 1449 |  |  |  |  |  |  | B class or sub-class thereof) or a literal | 
| 1450 |  |  |  |  |  |  | subject ID as a string. The subject cannot be searched for using the | 
| 1451 |  |  |  |  |  |  | "combined" key. | 
| 1452 |  |  |  |  |  |  |  | 
| 1453 |  |  |  |  |  |  | =item combined | 
| 1454 |  |  |  |  |  |  |  | 
| 1455 |  |  |  |  |  |  | The value should be a text string, and is searched against a combined field | 
| 1456 |  |  |  |  |  |  | that includes titles, authors and publisher names. | 
| 1457 |  |  |  |  |  |  |  | 
| 1458 |  |  |  |  |  |  | =item full | 
| 1459 |  |  |  |  |  |  |  | 
| 1460 |  |  |  |  |  |  | The value should be a text string, and is searched against almost all of the | 
| 1461 |  |  |  |  |  |  | textual data, including title, authors, publishers, summary, notes, award | 
| 1462 |  |  |  |  |  |  | information, etc. | 
| 1463 |  |  |  |  |  |  |  | 
| 1464 |  |  |  |  |  |  | =item dewey_decimal | 
| 1465 |  |  |  |  |  |  |  | 
| 1466 |  |  |  |  |  |  | The value should be a Dewey Decimal Classification number, and is used | 
| 1467 |  |  |  |  |  |  | directly in the search. | 
| 1468 |  |  |  |  |  |  |  | 
| 1469 |  |  |  |  |  |  | =item lcc_number | 
| 1470 |  |  |  |  |  |  |  | 
| 1471 |  |  |  |  |  |  | The value should be a Library of Congress Classification number, and is used | 
| 1472 |  |  |  |  |  |  | directly in the search. | 
| 1473 |  |  |  |  |  |  |  | 
| 1474 |  |  |  |  |  |  | =back | 
| 1475 |  |  |  |  |  |  |  | 
| 1476 |  |  |  |  |  |  | Note that the names above may not be the same as the corresponding parameters | 
| 1477 |  |  |  |  |  |  | to the service. The names are chosen to match the related attributes as | 
| 1478 |  |  |  |  |  |  | closely as possible, for ease of understanding. | 
| 1479 |  |  |  |  |  |  |  | 
| 1480 |  |  |  |  |  |  | =head1 EXAMPLES | 
| 1481 |  |  |  |  |  |  |  | 
| 1482 |  |  |  |  |  |  | Search for all books with "perl" in the title: | 
| 1483 |  |  |  |  |  |  |  | 
| 1484 |  |  |  |  |  |  | $perlbooks = WebService::ISBNDB::API::Books-> | 
| 1485 |  |  |  |  |  |  | search({ title => "perl" }); | 
| 1486 |  |  |  |  |  |  |  | 
| 1487 |  |  |  |  |  |  | Search for all books by Edgar Allan Poe: | 
| 1488 |  |  |  |  |  |  |  | 
| 1489 |  |  |  |  |  |  | $poebooks = WebService::ISBNDB::API::Books-> | 
| 1490 |  |  |  |  |  |  | search({ author => 'edgar allan poe' }); | 
| 1491 |  |  |  |  |  |  |  | 
| 1492 |  |  |  |  |  |  | Find the record for "Progamming Web Services With Perl": | 
| 1493 |  |  |  |  |  |  |  | 
| 1494 |  |  |  |  |  |  | $pwswp = WebService::ISBNDB::API::Books->find('0596002068'); | 
| 1495 |  |  |  |  |  |  |  | 
| 1496 |  |  |  |  |  |  | =head1 CAVEATS | 
| 1497 |  |  |  |  |  |  |  | 
| 1498 |  |  |  |  |  |  | The data returned by this class is only as accurate as the data retrieved from | 
| 1499 |  |  |  |  |  |  | B. | 
| 1500 |  |  |  |  |  |  |  | 
| 1501 |  |  |  |  |  |  | The list of results from calling search() is currently limited to 10 items. | 
| 1502 |  |  |  |  |  |  | This limit will be removed in an upcoming release, when iterators are | 
| 1503 |  |  |  |  |  |  | implemented. | 
| 1504 |  |  |  |  |  |  |  | 
| 1505 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 1506 |  |  |  |  |  |  |  | 
| 1507 |  |  |  |  |  |  | L, L, | 
| 1508 |  |  |  |  |  |  | L, L, | 
| 1509 |  |  |  |  |  |  | L, L | 
| 1510 |  |  |  |  |  |  |  | 
| 1511 |  |  |  |  |  |  | =head1 AUTHOR | 
| 1512 |  |  |  |  |  |  |  | 
| 1513 |  |  |  |  |  |  | Randy J. Ray Erjray@blackperl.comE | 
| 1514 |  |  |  |  |  |  |  | 
| 1515 |  |  |  |  |  |  | =head1 LICENSE | 
| 1516 |  |  |  |  |  |  |  | 
| 1517 |  |  |  |  |  |  | This module and the code within are | 
| 1518 |  |  |  |  |  |  | released under the terms of the Artistic License 2.0 | 
| 1519 |  |  |  |  |  |  | (http://www.opensource.org/licenses/artistic-license-2.0.php). This | 
| 1520 |  |  |  |  |  |  | code may be redistributed under either the Artistic License or the GNU | 
| 1521 |  |  |  |  |  |  | Lesser General Public License (LGPL) version 2.1 | 
| 1522 |  |  |  |  |  |  | (http://www.opensource.org/licenses/lgpl-license.php). | 
| 1523 |  |  |  |  |  |  |  | 
| 1524 |  |  |  |  |  |  | =cut |