File Coverage

blib/lib/WebFetch/Data/Store.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #
2             # WebFetch::Data::Store - WebFetch Embedding API top-level data store
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             # The WebFetch Embedding API manages the following data:
9             # * {data} - top level hash container (WebFetch::Data::Store)
10             # * {fields} - array of field names
11             # * {records} - array of data records (WebFetch::Data::Record)
12             # * each record is an array of data fields in the order of the field names
13             # * {wk_names} - hash of WebFetch well-known fields to actual field names
14             # * {feed} - top-level arbitrary info about the feed
15             #
16              
17             package WebFetch::Data::Store;
18              
19 1     1   1796 use strict;
  1         2  
  1         99  
20 1     1   8 use warnings;
  1         2  
  1         33  
21 1     1   45 use WebFetch;
  0            
  0            
22             use base qw( WebFetch );
23              
24             # define exceptions/errors
25             use Exception::Class (
26             );
27              
28             # no user-servicable parts beyond this point
29              
30             =head1 NAME
31              
32             WebFetch::Data::Store - Object for management of WebFetch data
33              
34             =head1 SYNOPSIS
35              
36             C
37              
38             C<$data = webfetch_obj-Edata;
39             $data-Eadd_fields( "field1", "field2", ... );
40             $num = $data-Enum_fields;
41             @field_names = $data-Eget_fields;
42             $name = $data-Efield_bynum( 3 );
43             $data-Eadd_wk_names( "title" =E "heading", "url" =E "link", ... );
44             $value = $data-Eget_feed( $name );
45             $data-Eset_feed( $name, $value );
46             $data-Eadd_record( $field1, $field2, ... ); # order corresponds to add_fields
47             $num = $data-Enum_records;
48             $record = $data-Eget_record( $n );
49             $data-Ereset_pos;
50             $record = $data-Enext_record;
51             $name = $data-Ewk2fname( $wk_name );
52             $num = $data-Efname2fnum( $field_name );
53             $num = $data-Ewk2fnum( $wk_name );
54             >
55              
56             =head1 DESCRIPTION
57              
58             This module provides access to the WebFetch data.
59             WebFetch instantiates the object for the input module.
60             The input module uses this to construct the data set from its input.
61             The output module uses the this to access the data and
62             produce its output object/format.
63              
64             =cut
65              
66             # initialization
67             sub init
68             {
69             my $self = shift;
70             $self->{fields} = [];
71             $self->{findex} = {};
72             $self->{records} = [];
73             $self->{wk_names} = {};
74             $self->{wkindex} = {};
75             $self->{feed} = {};
76              
77             # signal WebFetch that Data subclasses do not provide a fetch function
78             $self->{no_fetch} = 1;
79             $self->SUPER::init( @_ );
80              
81             return $self;
82             }
83              
84             =item $obj->add_fields( "field1", "field2", ... );
85              
86             Add the field names in the order their values will appear in the data table.
87              
88             =cut
89              
90             # add field names
91             sub add_fields
92             {
93             my $self = shift;
94             my @fields = @_;
95             my $field;
96             foreach $field ( @fields ) {
97             $self->{findex}{$field} = scalar @{$self->{fields}};
98             push @{$self->{fields}}, $field;
99             }
100             }
101              
102             =item $num = $obj->num_fields;
103              
104             Returns the number of fields/columns in the data.
105              
106             =cut
107              
108             # get number of fields
109             sub num_fields
110             {
111             my $self = shift;
112             return scalar @{$self->{fields}};
113             }
114              
115             =item @field_names = $obj->get_fields;
116              
117             Gets a list of the field names in the order their values appear in the data
118             table;
119              
120             =cut
121              
122             # get field names
123             sub get_fields
124             {
125             my $self = shift;
126             return keys %{$self->{fields}};
127             }
128              
129             =item $field_name = $obj->field_bynum( $num );
130              
131             Return a field name string based on the numeric position of the field.
132              
133             =cut
134              
135             # get field name by number
136             sub field_bynum
137             {
138             my $self = shift;
139             my $num = shift;
140             return $self->{fields}[$num];
141             }
142              
143             =item $obj->add_wk_names( "title" => "heading", "url" => "link", ... );
144              
145             Add associations between WebFetch well-known field names, which allows
146             WebFetch to apply meaning to these fields, such as titles, dates and URLs.
147             The parameters are pairs of well-known and actual field names.
148             Running this function more than once will add to the existing associations
149             of well-known to actual field names.
150              
151             =cut
152              
153             # add well-known names
154             sub add_wk_names
155             {
156             my $self = shift;
157             my ( $wk_name, $field );
158              
159             while ( @_ >= 2 ) {
160             $wk_name = shift;
161             $field = shift;
162             WebFetch::debug "add_wk_names $wk_name => $field";
163             $self->{wk_names}{$wk_name} = $field;
164             $self->{wkindex}{$wk_name} = $self->{findex}{$field};
165             }
166             }
167              
168             =item $value = $obj->get_feed( $name );
169              
170             Get an item of per-feed data by name.
171              
172             =cut
173              
174             # get feed info
175             sub get_feed
176             {
177             my $self = shift;
178             my $name = shift;
179             return (exists $self->{$name}) ? $self->{$name} : undef;
180             }
181              
182             =item $obj->set_feed( $name, $value );
183              
184             Set an item of per-feed data by name and value.
185              
186             =cut
187              
188             # set feed info
189             sub set_feed
190             {
191             my $self = shift;
192             my $name = shift;
193             my $value = shift;
194             my $retval = (exists $self->{$name}) ? $self->{$name} : undef;
195             $self->{$name} = $value;
196             return $retval;
197             }
198              
199             =item $obj->add_record( $value1, $value2, $value3, ... );
200              
201             Add a row to the end of the data table. Values must correspond to the
202             positions of the field names that were provided earlier.
203              
204             =cut
205              
206             # add a data record
207             # this adds the field values in the same order the field names were added
208             sub add_record
209             {
210             my $self = shift;
211             push @{$self->{records}}, [ @_ ];
212             }
213              
214             # TODO: add a function add_record_unordered( name => value, ... )
215             # less efficient, but may be OK for cases where that doesn't matter
216              
217             =item $num = $obj->num_records;
218              
219             Get the number of records/rows in the data table.
220              
221             =cut
222              
223             # get the number of data records
224             sub num_records
225             {
226             my $self = shift;
227             return scalar @{$self->{records}};
228             }
229              
230             =item $record = get_record( $num );
231              
232             Returns a WebFetch::Data::Record object for the row located
233             by the given row number in the data table. The first row is numbered 0.
234             Calling this function does not affect the position used by the next_record
235             function.
236              
237             =cut
238              
239             # get a data record by index
240             sub get_record
241             {
242             my $self = shift;
243             my $n = shift;
244             WebFetch::debug "get_record $n";
245             require WebFetch::Data::Record;
246             return WebFetch::Data::Record->new( $self, $n );
247             }
248              
249             =item $obj->reset_pos;
250              
251             Reset the position counter used by the next_record function back to the
252             beginning of the data table.
253              
254             =cut
255              
256             # reset iterator position
257             sub reset_pos
258             {
259             my $self = shift;
260              
261             WebFetch::debug "reset_pos";
262             delete $self->{pos};
263             }
264              
265             =item $record = $obj->next_record;
266              
267             The first call to this function returns the first record.
268             Each successive call to this function returns the following record until
269             the end of the data table.
270             After the last record, the function returns undef until
271             reset_pos is called to reset it back to the beginning.
272              
273             =cut
274              
275             # get next record
276             sub next_record
277             {
278             my $self = shift;
279              
280             # initialize if necessary
281             if ( !exists $self->{pos}) {
282             $self->{pos} = 0;
283             }
284             WebFetch::debug "next_record n=".$self->{pos}." of "
285             .scalar @{$self->{records}};
286              
287             # return undef if position is out of bounds
288             ( $self->{pos} < 0 ) and return undef;
289             ( $self->{pos} > scalar @{$self->{records}} - 1 ) and return undef;
290            
291             # get record
292             return $self->get_record( $self->{pos}++ );
293             }
294              
295             =item $obj->wk2fname( $wk )
296              
297             Obtain a field name from a well-known name.
298              
299             =cut
300              
301             # convert well-known name to field name
302             sub wk2fname
303             {
304             my $self = shift;
305             my $wk = shift;
306              
307             WebFetch::debug "wk2fname $wk => ".(( exists $self->{wk_names}{$wk}) ? $self->{wk_names}{$wk} : "undef");
308             return ( exists $self->{wk_names}{$wk})
309             ? $self->{wk_names}{$wk}
310             : undef;
311             }
312              
313             =item $obj->fname2fnum( $fname )
314              
315             Obtain a field number from a field name.
316              
317             =cut
318              
319             # convert a field name to a field number
320             sub fname2fnum
321             {
322             my $self = shift;
323             my $fname = shift;
324              
325             WebFetch::debug "fname2fnum $fname => ".(( exists $self->{findex}{$fname}) ? $self->{findex}{$fname} : "undef" );
326             return ( exists $self->{findex}{$fname})
327             ? $self->{findex}{$fname}
328             : undef;
329             }
330              
331             =item $obj->wk2fnum( $wk )
332              
333             Obtain a field number from a well-known name.
334              
335             =cut
336              
337             # convert well-known name to field number
338             sub wk2fnum
339             {
340             my $self = shift;
341             my $wk = shift;
342              
343             WebFetch::debug "wk2fnum $wk => ".(( exists $self->{wkindex}{$wk}) ? $self->{wkindex}{$wk} : "undef" );
344             return ( exists $self->{wkindex}{$wk})
345             ? $self->{wkindex}{$wk}
346             : undef;
347             }
348              
349             1;
350             __END__