File Coverage

blib/lib/WebFetch/Data/Record.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             #
2             # WebFetch::Data::Record - WebFetch Embedding API data record
3             #
4             # Copyright (c) 2009 Ian Kluft. This program is free software; you can
5             # redistribute it and/or modify it under the terms of the GNU General Public
6             # License Version 3. See http://www.webfetch.org/GPLv3.txt
7             #
8              
9             package WebFetch::Data::Record;
10              
11 1     1   1253 use strict;
  1         2  
  1         71  
12 1     1   13 use warnings;
  1         2  
  1         31  
13 1     1   5 use base qw( WebFetch );
  1         3  
  1         150  
14              
15             # define exceptions/errors
16             use Exception::Class (
17             'WebFetch::Data::Record::Exception::AutoloadFailure' => {
18             isa => 'WebFetch::TracedException',
19             alias => 'throw_autoload_fail',
20             description => "AUTOLOAD failed to handle function call",
21             },
22              
23             );
24              
25             # no user-servicable parts beyond this point
26              
27             =head1 NAME
28              
29             WebFetch::Data::Record - Object for management of WebFetch data records/rows
30              
31             =head1 SYNOPSIS
32              
33             C
34              
35             Cmk_field_accessor( $field_name, ... );
36             $value = $obj-Ebynum( $num );
37             $value = $obj->fieldname;
38             $obj->fieldname( $value );
39             >
40              
41             =head1 DESCRIPTION
42              
43             This module provides read-only access to a single record of the WebFetch data.
44              
45             =cut
46              
47             our $AUTOLOAD;
48              
49             # initialization
50             sub init
51             {
52             my $self = shift;
53              
54             # save parameters
55             $self->{obj} = shift;
56             $self->{num} = shift;
57             $self->{recref} = $self->{obj}{records}[$self->{num}];
58              
59             # signal WebFetch that Data subclasses do not provide a fetch function
60             $self->{no_fetch} = 1;
61             $self->SUPER::init( @_ );
62              
63             # make accessor functions
64             my $field;
65             my $class = ref( $self );
66             foreach $field ( @{$self->{obj}{fields}}) {
67             $class->mk_field_accessor( $field );
68             }
69             foreach $field ( keys %{$self->{obj}{wk_names}}) {
70             $class->mk_field_accessor( $field );
71             }
72            
73             return $self;
74             }
75              
76             # shortcut function to top-level WebFetch object data
77             sub data { return $_[0]->{obj}; }
78              
79             =item $value = $obj->bynum( $field_num );
80              
81             Returns the value of the field located by the field number provided.
82             The first field is numbered 0.
83              
84             =cut
85              
86             # get a field by number
87             sub bynum
88             {
89             my $self = shift;
90             my $f = shift;
91              
92             WebFetch::debug "bynum $f";
93             return $self->{recref}[$f];
94             }
95              
96             =item $value = $obj->byname( $field_name );
97              
98             Returns the value of the named field.
99              
100             =cut
101              
102             # get a field by name
103             sub byname
104             {
105             my $self = shift;
106             my $fname = shift;
107             my $obj = $self->{obj};
108             my $f;
109              
110             WebFetch::debug "byname ".(( defined $fname ) ? $fname : "undef");
111             ( defined $fname ) or return undef;
112             if ( exists $obj->{findex}{$fname}) {
113             $f = $obj->{findex}{$fname};
114             return $self->{recref}[$f];
115             }
116             return undef;
117             }
118              
119             =item $class->mk_field_accessor( $field_name, ... );
120              
121             Creates accessor functions for each field name provided.
122              
123             =cut
124              
125             # make field accessor/mutator functions
126             sub mk_field_accessor
127             {
128             my $class = shift;
129             my $name;
130            
131             foreach $name ( @_ ) {
132             no strict 'refs';
133             $class->can( $name ) and next; # skip if function exists!
134              
135             # make a closure which keeps value of $name from this call
136             # keep generic so code can use more than one data type per run
137             *{$class."::".$name} = sub {
138             my $self = shift;
139             my $value = shift;
140             my $obj = $self->{obj};
141             my $recref = $self->{recref};
142             my $f;
143             if ( exists $obj->{findex}{$name}) {
144             $f = $obj->{findex}{$name};
145             if ( defined $value ) {
146             my $tmp = $recref->[$f];
147             $recref->[$f] = $value;
148             return $tmp;
149             } else {
150             return $recref->[$f];
151             }
152             } elsif ( exists $obj->{wk_names}{$name}) {
153             my $wk = $obj->{wk_names}{$name};
154             $f = $obj->{findex}{$wk};
155             if ( defined $value ) {
156             my $tmp = $recref->[$f];
157             $recref->[$f] = $value;
158             return $tmp;
159             } else {
160             return $recref->[$f];
161             }
162             } else {
163             return undef;
164             }
165             };
166             }
167             }
168              
169             =item accessor functions
170              
171             Accessor functions are created for field names and
172             well-known names as they are defined.
173              
174             So a field named "title" can be accessed by an object method of the same
175             name, like $obj->title .
176              
177             =cut
178              
179             # AUTOLOAD function to provide field accessors/mutators
180             sub AUTOLOAD
181             {
182             my $self = shift;
183             my $type = ref($self) or throw_autoload_fail "self is not an object";
184              
185             my $name = $AUTOLOAD;
186             $name =~ s/.*://; # strip fully-qualified portion, just want function
187              
188             # decline all-caps names - reserved for special Perl functions
189             ( $name =~ /^[A-Z]+$/ ) and return;
190              
191             WebFetch::debug __PACKAGE__."::AUTOLOAD $name";
192             if (( exists $self->{obj}{findex}{$name})
193             or ( exists $self->{obj}{wk_names}{$name}))
194             {
195             $type->mk_field_accessor( $name );
196             return $self->$name(@_);
197             } else {
198             throw_autoload_fail "no such function or field $name";
199             }
200             }
201              
202             1;
203             __END__