The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# vim: sts=3 sw=3 et
package Parse::CPAN::Whois;
use strict;
use warnings;

our $VERSION='0.02';

=head1 NAME

Parse::CPAN::Whois - Parse CPAN's authors/00whois.xml file

=head1 DESCRIPTION

CPAN has two author indices, "01mailrc.txt.gz", which L<Parse::CPAN::Authors> parses for you, and "00whois.xml", which is handled by this module.

It tries to be API-compatible with L<Parse::CPAN::Authors>, while providing
access to the extra information "00whois.xml" has over "01mailrc.txt.gz".

=cut

use XML::SAX::ParserFactory;
use Parse::CPAN::Whois::Author;

use base qw(XML::SAX::Base);

=head1 METHODS

=head2 new FILENAME|DATA

new() takes either a path or a scalar containing the data to parse
as an argument. It parses the data, and then returns an object you
can query for PAUSE ids.

=cut

sub new {
   my $class = shift;
   my $file = shift;

   $file = '00whois.xml' unless (defined $file);

   my $handler = $class->SUPER::new;
   my $p = XML::SAX::ParserFactory->parser(Handler => $handler);
   if (substr ($file, 0, 1) eq '<') {
      $p->parse_string ($file);
   } else {
      $p->parse_file($file);
   }

   return delete $handler->{list};
}

=head2 author PAUSEID

returns the L<Parse::CPAN::Whois::Author> object that corresponds to
the PAUSE id.

=cut

sub author {
   my $self = shift;
   my $cpanid = shift;

   return $self->{uc($cpanid)}
}

=head2 authors

returns a list of L<Parse::CPAN::Whois::Author> objects.

=cut

sub authors {
   my $self = shift;

   return values %$self;
}


# below are the SAX2 methods used.


sub start_element {
   my $self = shift;
   my $elem = shift;

   if ($elem->{LocalName} eq 'cpan-whois') {
      $self->{list} = bless {}, 'Parse::CPAN::Whois';
   } elsif ($elem->{LocalName} eq 'cpanid') {
      $self->{tmp} = bless {}, 'Parse::CPAN::Whois::Author';
   } else {
      $self->{key} = $elem->{LocalName};
      $self->{value} = '';
   }
}

sub characters {
   my $self = shift;
   my $data = shift;

   if (defined $self->{value}) {
      $self->{value} .= $data->{Data};
   }
}

sub end_element {
   my $self = shift;
   my $elem = shift;

   if ($elem->{LocalName} eq 'cpan-whois') {
   } elsif ($elem->{LocalName} eq 'cpanid') {
      my $id = $self->{tmp}->{id};
      my $foo = delete $self->{tmp};
      if ($foo->{type} eq 'author') {
         $self->{list}->{$id} = $foo;
      }
   } else {
      $self->{tmp}->{delete $self->{key}} = delete $self->{value};
   }
}

1;

__END__

=head1 SEE ALSO

L<Parse::CPAN::Authors>

=head1 AUTHOR

Martijn van Beers  <martijn@cpan.org>

=head1 LICENSE

Copyright (c) 2008, Martijn van Beers

This module is free software; you can redistribute it or modify it under
the GPL, version 2 or higher. See the LICENSE file for details.