File Coverage

blib/lib/WebService/Lucene/Document.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             package WebService::Lucene::Document;
2              
3 2     2   8885 use strict;
  2         4  
  2         88  
4 2     2   12 use warnings;
  2         4  
  2         73  
5              
6 2     2   10 use base qw( WebService::Lucene::Client Class::Accessor::Fast );
  2         4  
  2         939  
7              
8             use WebService::Lucene::Field;
9             use WebService::Lucene::XOXOParser;
10             use XML::Atom::Entry;
11              
12             __PACKAGE__->mk_accessors( qw( fields_ref base_url title relevance ) );
13              
14             BEGIN {
15             for my $type ( WebService::Lucene::Field->types ) {
16             no strict 'refs';
17             *{ __PACKAGE__ . "\::add_$type" } = sub {
18             shift->add( WebService::Lucene::Field->$type( @_ ) );
19             }
20             }
21             }
22              
23             =head1 NAME
24              
25             WebService::Lucene::Document - Object to represent a Lucene Document
26              
27             =head1 SYNOPSIS
28              
29             # Create a new document
30             $doc = WebService::Lucene::Document->new;
31            
32             # add a field
33             $doc->add( $field );
34              
35             =head1 DESCRIPTION
36              
37             Object to represent a Lucene Document.
38              
39             =head1 METHODS
40              
41             =head2 new( )
42              
43             Creates an empty document.
44              
45             =cut
46              
47             sub new {
48             my $class = shift;
49             my $self = $class->SUPER::new;
50              
51             $self->clear_fields;
52              
53             return $self;
54             }
55              
56             =head2 create()
57              
58             Sends a create request for this document.
59              
60             =cut
61              
62             sub create {
63             my ( $self ) = @_;
64             my $url = $self->base_url;
65              
66             $url =~ s{[^/]+/?$}{};
67              
68             my $new_url = $self->createEntry( $url, $self->as_entry );
69             $self->base_url( $new_url );
70              
71             return $self;
72             }
73              
74             =head2 new_from_entry( $entry )
75              
76             Takes an L and constructs a new object.
77              
78             =cut
79              
80             sub new_from_entry {
81             my ( $class, $entry ) = @_;
82             my $self = $class->new;
83              
84             if ( $entry->link ) {
85             $self->base_url( $entry->link->href );
86             }
87              
88             $self->relevance(
89             $entry->get( 'http://a9.com/-/opensearch/extensions/relevance/1.0/', 'score' ) );
90             $self->title( $entry->title );
91             my $content = $entry->content->body;
92              
93             my @properties = WebService::Lucene::XOXOParser->parse( $content );
94              
95             if ( @properties and $properties[ 0 ]->{ class } ) {
96             for my $property ( @properties ) {
97             my %attrs = map { $_ => 1 } split( / /, $property->{ class } );
98             my $method
99             = 'add_' . WebService::Lucene::Field->get_type( \%attrs );
100             $self->$method( map { $property->{ $_ } } qw( name value ) );
101             }
102             }
103             else {
104             $self->fields_ref(
105             { $self->title =>
106             [ map { $_->{ name } => $_->{ value } } @properties ]
107             }
108             );
109             }
110              
111             return $self;
112             }
113              
114             =head2 add( @fields )
115              
116             Adds each field to the document.
117              
118             =cut
119              
120             sub add {
121             my $self = shift;
122             my $fields = $self->fields_ref;
123              
124             while ( my $field = shift ) {
125             my $name = $field->name;
126             unless ( exists $fields->{ $name } ) {
127             $fields->{ $name } = [];
128             }
129             unless ( $self->can( $name ) ) {
130             no strict 'refs';
131             *{ ref( $self ) . "\::$name" } = _field_accessor( $name );
132             }
133              
134             push @{ $fields->{ $name } }, $field;
135             }
136             }
137              
138             =head2 add_keyword( $name => $value )
139              
140             Auto-generated shortcuts to add a "keyword" field.
141              
142             =head2 add_sorted $name => $value )
143              
144             Auto-generated shortcuts to add a "sorted" field.
145              
146             =head2 add_text( $name => $value )
147              
148             Auto-generated shortcuts to add a "keyword" field.
149              
150             =head2 add_unindexed( $name => $value )
151              
152             Auto-generated shortcuts to add a "keyword" field.
153              
154             =head2 add_unstored( $name => $value )
155              
156             Auto-generated shortcuts to add a "keyword" field.
157              
158             =head2 title( [$title] )
159              
160             The title of the document, set from search or listing results.
161              
162             =head2 relevance( [$relevance] )
163              
164             A floating point number (0..1) set from search results.
165              
166             =head2 fields_ref( [$fields] )
167              
168             A name-keyed hashref of field objects.
169              
170             =head2 facets()
171              
172             Technically an alias for fields. But should only be used when fetching
173             facet results.
174              
175             =cut
176              
177             *facets = \&fields;
178              
179             =head2 get( [$name] )
180              
181             Alias for C.
182              
183             =cut
184              
185             *get = \&fields;
186              
187             =head2 fields( [$name] )
188              
189             Returns all fields named <$name> or all fields if no name
190             is specified.
191              
192             =cut
193              
194             sub fields {
195             my $self = shift;
196             my $name = shift;
197             my $fieldsref = $self->fields_ref;
198              
199             if ( $name ) {
200             my $fields = $fieldsref->{ $name };
201             return () unless defined $fields;
202             return wantarray ? @$fields : $fields->[ 0 ];
203             }
204              
205             return map { @{ $fieldsref->{ $_ } } } keys %$fieldsref;
206             }
207              
208             =head2 clear_fields( )
209              
210             Removes all fields from this document
211              
212             =cut
213              
214             sub clear_fields {
215             shift->fields_ref( {} );
216             }
217              
218             =head2 remove_field( $field )
219              
220             Remove a particular field from the document
221              
222             =cut
223              
224             sub remove_field {
225             my $self = shift;
226             my $field = shift;
227              
228             {
229             no strict 'refs';
230             undef *{ ref( $self ) . "\::$field" };
231             }
232              
233             return delete $self->fields_ref->{ $field };
234             }
235              
236             =head2 as_entry( )
237              
238             Generates an L object for the current document.
239              
240             =cut
241              
242             sub as_entry {
243             my ( $self ) = @_;
244              
245             my $entry = XML::Atom::Entry->new;
246             $entry->title( $self->title || 'New Entry' );
247              
248             my @properties;
249             for my $field ( $self->fields ) {
250             my $types = $field->get_info;
251              
252             push @properties,
253             {
254             name => $field->name,
255             value => $field->value,
256             class => join( ' ', grep { $types->{ $_ } } keys %$types )
257             };
258             }
259             my $xml = WebService::Lucene::XOXOParser->construct( @properties );
260              
261             $entry->content( $xml );
262             $entry->content->type( 'xhtml' );
263              
264             return $entry;
265              
266             }
267              
268             =head2 update( )
269              
270             Updates the document in the index.
271              
272             =cut
273              
274             sub update {
275             my ( $self ) = @_;
276             $self->updateEntry( $self->base_url, $self->as_entry );
277             }
278              
279             =head2 delete( )
280              
281             Delete the document from the index.
282              
283             =cut
284              
285             sub delete {
286             my ( $self ) = @_;
287             $self->deleteEntry( $self->base_url );
288             }
289              
290             =head2 _field_accessor( $name )
291              
292             Generates a closure for accessing a field.
293              
294             =cut
295              
296             sub _field_accessor {
297             my $name = shift;
298             return sub {
299             my $self = shift;
300             my $fields = $self->fields_ref->{ $name };
301              
302             return unless defined $fields;
303              
304             my @values
305             = map { $_->value } ( wantarray ? @$fields : $fields->[ 0 ] );
306             return wantarray ? @values : $values[ 0 ];
307             }
308             }
309              
310             =head1 AUTHORS
311              
312             =over 4
313              
314             =item * Brian Cassidy Ebrian.cassidy@nald.caE
315              
316             =item * Adam Paynter Eadam.paynter@nald.caE
317              
318             =back
319              
320             =head1 COPYRIGHT AND LICENSE
321              
322             Copyright 2006-2009 National Adult Literacy Database
323              
324             This library is free software; you can redistribute it and/or modify
325             it under the same terms as Perl itself.
326              
327             =cut
328              
329             1;