| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package WebService::Libris::Book; | 
| 2 | 1 |  |  | 1 |  | 7 | use Mojo::Base 'WebService::Libris'; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 3 | 1 |  |  | 1 |  | 685 | use WebService::Libris::Utils qw/marc_lang_code_to_iso/; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 151 |  | 
| 4 | 1 |  |  | 1 |  | 8 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 32 |  | 
| 5 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 31 |  | 
| 6 | 1 |  |  | 1 |  | 27 | use 5.010; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 908 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | __PACKAGE__->_make_text_accessor(qw/title date publisher/, ['isbn', 'isbn10']); | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | sub fragments { | 
| 11 | 1 |  |  | 1 | 1 | 22 | 'bib', shift->id; | 
| 12 |  |  |  |  |  |  | } | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 0 |  |  | 0 | 1 | 0 | sub related_books { shift->list_from_dom('frbr_related') } | 
| 15 | 1 |  |  | 1 | 1 | 500 | sub held_by       { shift->list_from_dom('held_by')      } | 
| 16 | 1 |  |  | 1 | 1 | 14 | sub authors_obj   { shift->list_from_dom('creator')      } | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | sub authors_text  { | 
| 19 | 1 |  |  | 1 | 1 | 1725 | my $self = shift; | 
| 20 | 1 |  |  |  |  | 6 | my @authors = grep length, map $_->text, $self->dom->find('creator')->each; | 
| 21 |  |  |  |  |  |  | # XXX: come up with something better | 
| 22 | 1 | 50 |  |  |  | 2563 | if (wantarray) { | 
|  |  | 0 |  |  |  |  |  | 
| 23 | 1 |  |  |  |  | 10 | return @authors; | 
| 24 |  |  |  |  |  |  | } elsif (@authors == 1) { | 
| 25 | 0 |  |  |  |  | 0 | return $authors[0] | 
| 26 |  |  |  |  |  |  | } else { | 
| 27 | 0 |  |  |  |  | 0 | return join ", ", @authors; | 
| 28 |  |  |  |  |  |  | } | 
| 29 |  |  |  |  |  |  | } | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | sub isbns { | 
| 32 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 33 | 0 |  |  |  |  | 0 | map $_->text, $self->dom->find('isbn10')->each; | 
| 34 |  |  |  |  |  |  | } | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | sub authors_ids { | 
| 37 | 2 |  |  | 2 | 0 | 627 | my $self = shift; | 
| 38 | 2 |  |  |  |  | 4 | my %seen; | 
| 39 | 2 |  |  |  |  | 16 | my @ids = sort | 
| 40 | 2 |  |  |  |  | 85 | grep { !$seen{$_}++ } | 
| 41 | 6 |  |  |  |  | 3802 | map { (split '/', $_)[-1] } | 
| 42 |  |  |  |  |  |  | grep $_, | 
| 43 | 2 |  |  |  |  | 15 | map { $_->attr('rdf:resource') } | 
| 44 |  |  |  |  |  |  | $self->dom->find('creator')->each; | 
| 45 | 2 |  |  |  |  | 28 | return @ids; | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | sub languages_marc { | 
| 49 | 2 |  |  | 2 | 0 | 3 | my $self = shift; | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 2 |  |  |  |  | 9 | my @l = $self->dom->find('language')->each; | 
| 52 | 2 |  |  |  |  | 3645 | @l = grep $_, map $_->attr('rdf:resource'), @l; | 
| 53 | 2 | 50 |  |  |  | 111 | return undef unless @l; | 
| 54 |  |  |  |  |  |  |  | 
| 55 | 2 | 50 |  |  |  | 5 | map { m{http://purl.org/NET/marccodes/languages/(\w{3})(?:\#lang)?} && "$1" } @l; | 
|  | 2 |  |  |  |  | 43 |  | 
| 56 |  |  |  |  |  |  | } | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | sub language_marc { | 
| 59 | 0 |  | 0 | 0 | 1 | 0 | (shift->languages_marc)[-1] // () | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | sub languages { | 
| 63 | 2 |  |  | 2 | 1 | 4 | my $self = shift; | 
| 64 | 2 |  |  |  |  | 8 | my @langs = map marc_lang_code_to_iso($_), $self->languages_marc; | 
| 65 | 2 |  |  |  |  | 10 | for ($self->dom->find('*[lang]')->each) { | 
| 66 | 6 |  |  |  |  | 4844 | my $l = $_->attr('xml:lang'); | 
| 67 | 6 | 50 |  |  |  | 258 | push @langs, $l if defined $l; | 
| 68 |  |  |  |  |  |  | } | 
| 69 | 2 |  |  |  |  | 26 | @langs; | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | sub language { | 
| 73 | 2 |  |  | 2 | 1 | 1467 | my $self = shift; | 
| 74 | 2 |  |  |  |  | 9 | my @langs = $self->languages; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 2 | 50 |  |  |  | 7 | return undef unless @langs; | 
| 77 | 2 |  |  |  |  | 4 | my %c; | 
| 78 | 2 |  |  |  |  | 17 | ++$c{$_} for @langs; | 
| 79 |  |  |  |  |  |  | # just one language | 
| 80 | 2 | 50 |  |  |  | 25 | return $langs[0] if keys(%c) == 1; | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 0 |  |  |  |  |  | @langs = reverse sort { $c{$a} <=> $c{$b} } @langs; | 
|  | 0 |  |  |  |  |  |  | 
| 83 | 0 | 0 |  |  |  |  | return $langs[0] if $c{$langs[0]} - $c{$langs[1]} >= 2; | 
| 84 | 0 |  |  |  |  |  | return undef; | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | =head1 NAME | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | WebService::Libris::Book - represents a Book in the libris.kb.se webservice | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | use WebService::Libris; | 
| 94 |  |  |  |  |  |  | for my $b (WebService::Libris->search(term => 'Rothfuss')) { | 
| 95 |  |  |  |  |  |  | # $b is a WebService::Libris::Book object here | 
| 96 |  |  |  |  |  |  | say $b->title; | 
| 97 |  |  |  |  |  |  | say $b->isbn; | 
| 98 |  |  |  |  |  |  | } | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | C is a subclass of C and | 
| 103 |  |  |  |  |  |  | inherits all its methods. | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | All of the following methods return undef or the empty list if the information is not available. | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | =head1 METHODS | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | =head2 title | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | returns the title of the book | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | =head2 date | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | returns the publication date as a string (often just a year) | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | =head2 isbn | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | returns the first ISBN | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | =head2 isbn | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | returns a list of all ISBNs associated with the current book | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | =head2 publisher | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | returns the name of the publisher | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | =head2 related_books | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | returns a list of related books | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | =head2 held_by | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | returns a list of libraries that hold this book | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | =head2 authors_obj | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | returns a list of L objects which are listed | 
| 140 |  |  |  |  |  |  | as I of this book. | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | =head2 authors_text | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | returns a list of creators of this book, as extracted from the response. | 
| 145 |  |  |  |  |  |  | This often contains duplicates, or slightly different versions of the | 
| 146 |  |  |  |  |  |  | same author name, so should be used with care. | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | =head2 language_marc | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | Returns the language in the three-letter "MARC" code, or undef if no such | 
| 151 |  |  |  |  |  |  | code is found. | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | =head2 language | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | Some of the book records include a "MARC" language code (same as the | 
| 156 |  |  |  |  |  |  | Library of Congress uses).  This methods tries to extract this code, and returns | 
| 157 |  |  |  |  |  |  | the equivalent ISO 639 language code (two letters) if the translation is known. | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | It also exracts C attribute from any tags found in the record. | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | Sometimes there are several different language specifications in a single | 
| 162 |  |  |  |  |  |  | record.  In this case this method does an educated guess which one is correct. | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | =head2 languages | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | Return all language codes mentioned in the description of the C method. No deduplication is done. | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | =cut | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | 1; |