package OpenInteract2::FullTextIterator;

# $Id: FullTextIterator.pm,v 1.2 2005/03/18 04:09:48 lachoy Exp $

use strict;
use base qw( SPOPS::Iterator );
use Log::Log4perl            qw( get_logger );
use OpenInteract2::Constants qw( :log );
use SPOPS::Iterator          qw( ITER_IS_DONE );

$OpenInteract2::FullTextIterator::VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);

my ( $log );

sub initialize {
    my ( $self, $p ) = @_;
    $log ||= get_logger( LOG_APP );

    $self->{_FT_RESULTS}       = $p->{results};
    $self->{_FT_COUNT}         = 0;
    $self->{_FT_RAW_COUNT}     = 0;
    $self->{_FT_OFFSET}        = $p->{min} || $p->{offset};
    $self->{_FT_MAX}           = $p->{max};
}


sub fetch_object {
    my ( $self ) = @_;

    # Get the info for retrieving the object

    my $current_count = $self->{_FT_RAW_COUNT};

    my ( $class, $id, $fulltext_score, $term_occur );

    if ( ref $self->{_FT_RESULTS} ) {
        my $current_rec = $self->{_FT_RESULTS}->[ $current_count ];
        $class          = $current_rec->[0];
        $id             = $current_rec->[1];
        $fulltext_score = $current_rec->[2];
        $term_occur     = $current_rec->[3];
    }

    # If there's no class/oid, go on to the next

    unless ( $class and $id ) {
        $self->{_FT_RAW_COUNT}++;
        return $self->fetch_object;
    }

    my $obj = eval {
        $class->fetch( $id, { skip_security => $self->{_SKIP_SECURITY} } )
    };
    if ( $@ ) {
        $log->warn( "Caught error fetching [$class: $id]: $@" );
        $self->{_FT_RAW_COUNT}++;
        return $self->fetch_object;
    }

    unless ( $obj ) {
        $self->{_FT_RAW_COUNT}++;
        return $self->fetch_object;
    }

    # Using min/max and haven't reached it yet

    if ( $self->{_FT_OFFSET} and 
         ( $self->{_FT_COUNT} < $self->{_FT_OFFSET} ) ) {
        $self->{_FT_COUNT}++;
        $self->{_FT_RAW_COUNT}++;
        return $self->fetch_object;
    }

    if ( $self->{_FT_MAX} and
         ( $self->{_FT_COUNT} > $self->{_FT_MAX} ) ) {
        return ITER_IS_DONE;
    }

    # Ok, we've gone through all the necessary contortions -- we can
    # actually return the object.

    if ( UNIVERSAL::isa( $obj, 'SPOPS' ) ) {
        $obj->{tmp_fulltext_score} = $fulltext_score;
        $obj->{tmp_fulltext_term_count} = $term_occur;
    }

    $self->{_FT_RAW_COUNT}++;
    $self->{_FT_COUNT}++;

    return wantarray ? ( $obj, $self->{_FT_COUNT}, $fulltext_score ) : $obj;
}

1;

__END__

=head1 NAME

OpenInteract2::FullTextIterator - Iterator to scroll through search results

=head1 SYNOPSIS

 my $indexer = CTX->fulltext_indexer;
 my $iterator = $indexer->search_index({
     terms        => [ 'mario', 'lemieux' ],
     search_type  => 'and',
     return       => 'iterator'
 });
 
 # just get the object...
 while ( my $obj = $iter->get_next ) {
     print "Object is a ", ref( $obj ), " with ID ", $obj->id, "\n";
 }
 
 # ...or get additional information as well
 while ( my ( $obj, $count, $score ) = $iter->get_next ) {
     print "Object #$count is a ", ref( $obj ), " with ID ", $obj->id, " ",
           "and search score $score\n";
 }

=head1 DESCRIPTION

This class implements L<SPOPS::Iterator|SPOPS::Iterator> so we can
scroll through search results one at a time. The results do not have
to be SPOPS objects but they do need to implement B<fetch( $id )> as a
class method to return a new object.

=head1 METHODS

B<initialize>

See our instance properties:

=over 4

=item *

B<results>: Arrayref of results as generated by
L<OpenInteract2::ResultsManage> or something similar.

=item *

B<min>: Start returning objects at this place number.

=item *

B<max>: Stop returning objects at this place number.

=back

B<fetch_object>

Return the next object.

=head1 SEE ALSO

L<SPOPS::Iterator|SPOPS::Iterator>

L<OpenInteract2::FullTextIndexer|OpenInteract2::FullTextIndexer>

=head1 COPYRIGHT

Copyright (c) 2001-2005 Chris Winters. All rights reserved.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 AUTHORS

Chris Winters E<lt>chris@cwinters.comE<gt>
