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; |