package Lingua::EN::NameParse::Simple;

use warnings;
use strict;
use DBI; 
use DB_File; 
use Fcntl ':flock'; 
use locale;  

=head1 NAME

Lingua::EN::NameParse::Simple - Parse an English name into component parts 

=head1 VERSION

Version 0.10

=cut

our $VERSION = '0.10';

=head1 SYNOPSIS

Invoke this package as follows:  

	use parser.pm; 
	my %name = Lingua::EN::NameParse::Simple::ParseName($fullname); 
	# %name will contain available values for these keys:  
	# TITLE, FIRST, MIDDLE, LAST, SUFFIX

=head1 FUNCTIONS

=head2 ParseName 

my %name = Lingua::EN::NameParse::Simple::ParseName($fullname); 

returns values for these keys:
TITLE, FIRST, MIDDLE, LAST, SUFFIX

=cut

sub ParseName {
  my(@returnarray,$namearraysize,$i,$j); 
  my(@namearray,$fullname,@validtitle,@validsuffix); 
  my($titlematch,%name);
  my($nameelement,$tmp,$lnamematch,$mnamematch); 
  my($fnamematch,,$suffixmatch,$tmpelement);
  $fullname=$_[0];
  @namearray=split(/\s+/,$fullname);
  @validtitle = ('MR', 'MS', 'MRS', 'MISS', 'DR', 'DOCTOR', 'REV', 'REVEREND', 'PASTOR', 'HONORABLE'); 
  @validsuffix = ('SR', 'SENIOR', 'JR', 'JUNIOR', 'II', 'III', 'IV');  
  $namearraysize=@namearray; # Number of items in array
  $i=0; # Keep track of name element
  $titlematch=0; 
  $lnamematch=0; 
  $mnamematch=0;
  $fnamematch=0; 
  $suffixmatch=0;
  NAMEPARSE:foreach(@namearray) {
    $nameelement=$_;
    if(($i+1) == $namearraysize) {
      # Test to see if last element
      # Either Suffix or Last Name
      foreach(@validsuffix) {
        $tmp=uc($nameelement);
        $tmp=~s/\[,.]//g;
        $tmp=~s/\,//g;
        $tmp=~s/\.//g;
        if($tmp eq $_) {
          # Suffix detected
          $returnarray[$i][0]="SUFFIX";
          $nameelement=~s/\[,.]//g;
          $returnarray[$i][1]=$nameelement;
          $suffixmatch++;
          if($lnamematch == 0 && $returnarray[$i-1][0] eq "MIDDLE") {
            # If no last name has been found then next to last element
            # that is a middle name becomes the last name
            $returnarray[$i-1][0] = "LAST";
          }
          $i++;
          next NAMEPARSE;
        }
      }
      if($lnamematch == 0) {
        # Since Suffix is not found and lastname not found
        # must be a last name
        $returnarray[$i][0]="LAST";
        $nameelement=~s/\.//g;
        $nameelement=~s/\,//g;
        $returnarray[$i][1]=$nameelement;
        $lnamematch++;
        $i++;
        next NAMEPARSE;
      } else {
        # Must be a middle name
        $returnarray[$i][0]="MIDDLE";
        $nameelement=~s/\[,.]//g;
        $returnarray[$i][1]=$nameelement;
        $mnamematch=1;
        $i++;
        next NAMEPARSE;
      }
    } elsif(($i+2) == $namearraysize) {
      # Test to see if second to last element
      # See if element is part of the first 3
      if($i < 3) {
        # Part of first 3 crucial elements
        if($i == 0) {
          # Two element array, first element
          # Check to see if title
          VALIDTITLE:foreach(@validtitle) {
            # See if there is a title match
            $tmp=uc($nameelement);
            $tmp=~s/\[.,]//g;
            $tmp=~s/\,//g;
            $tmp=~s/\.//g;
            # print "$tmp vs $_ test var\n"; 
            if($tmp eq $_) {
              # Match!
              $returnarray[$i][0]="TITLE";
              $returnarray[$i][1]=$nameelement;
              $titlematch++;
              $i++;
              next NAMEPARSE;
            }
          }
          if(substr($nameelement,length($nameelement)-1,1) eq ",") {
            # Check to see if last name
            $returnarray[$i][0]="LAST";
            $returnarray[$i][1]=$nameelement;
            $lnamematch++;
            $i++;
            next NAMEPARSE;
          } else {
            # Otherwise, must be a first name
            $returnarray[$i][0]="FIRST";
            $returnarray[$i][1]=$nameelement;
            $fnamematch++;
            $i++;
            next NAMEPARSE;
          }
        } elsif($i == 1) {
          # Three element array, second element
          if($returnarray[$i-1][0] eq "TITLE" || $returnarray[$i-1][0] eq "LAST") {
            # Must be a first name
            $returnarray[$i][0]="FIRST";
            $nameelement=~s/\,//g;
            $nameelement=~s/\.//g;
            $returnarray[$i][1]=$nameelement;
            $fnamematch=1;
            $i++;
            next NAMEPARSE;
          } elsif($returnarray[$i-1][0] eq "FIRST") {
            # Must be a middle name
            $returnarray[$i][0]="MIDDLE";
            $nameelement=~s/\,//g;
            $nameelement=~s/\.//g;
            $returnarray[$i][1]=$nameelement;
            $mnamematch=1;
            $i++;
            next NAMEPARSE;
          }
        } elsif($i == 2) {
          # Four element array, third element
          # Must be a middle or a last name but must set to middle until last element is detected
          $returnarray[$i][0]="MIDDLE";
          $nameelement=~s/\,//g;
          $nameelement=~s/\.//g;
          $returnarray[$i][1]=$nameelement;
          $mnamematch=1;
          $i++;
          next NAMEPARSE;
        }
      } else {
        # Must be a middle (or last name but won't know that
        # until we check the last element so set to middle name)
        $returnarray[$i][0]="MIDDLE";
        $nameelement=~s/\,//g;
        $nameelement=~s/\.//g;
        $returnarray[$i][1]=$nameelement;
        $mnamematch=1;
        $i++;
        next NAMEPARSE;
      }
    } elsif($i > 2 && ($i+2) < $namearraysize) {
      # All elements after the 3rd and before 2nd to last
      $returnarray[$i][0]="MIDDLE";
      $nameelement=~s/\,//g;
      $nameelement=~s/\.//g;
      $returnarray[$i][1]=$nameelement;
      $mnamematch=1;
      $i++;
      next NAMEPARSE;
    } elsif($i == 0) {
      # Test to see if first element
      # Test to see if this is a title
      VALIDTITLE:foreach(@validtitle) {
        # See if there is a title match
        $tmp=uc($nameelement);
        $tmp=~s/\[.,]//g;
        $tmp=~s/\,//g;
        $tmp=~s/\.//g;
        # print "$tmp vs $_ test var\n"; 
        if($tmp eq $_) {
          # Match!
          $returnarray[$i][0]="TITLE";
          $returnarray[$i][1]=$nameelement;
          $titlematch++;
          $i++;
          next NAMEPARSE;
        }
      }
      if(substr($nameelement,length($nameelement)-1,1) eq ",") {
        # Detected a last name
        $returnarray[$i][0]="LAST";
        $nameelement=~s/\,//g;
        $nameelement=~s/\.//g;
        $returnarray[$i][1]=$nameelement;
        $i++;
        $lnamematch++;
        next NAMEPARSE;
      } else {
        # If all else fails, must be first name
        $returnarray[$i][0]="FIRST";
        $nameelement=~s/\,//g;
        $nameelement=~s/\.//g;
        $returnarray[$i][1]=$nameelement;
        $i++;
        $fnamematch++;
        next NAMEPARSE;
      }
    } elsif($i == 1) {
      # Test to see if second element
      if($returnarray[$i-1][0] eq "TITLE" || $returnarray[$i-1][0] eq "LAST") {
        # First Name
        $returnarray[$i][0]="FIRST";
        $nameelement=~s/\,//g;
        $nameelement=~s/\.//g;
        $returnarray[$i][1]=$nameelement;
        $i++;
        $fnamematch++;
        next NAMEPARSE;
      } else {
        # Middle Name
        $returnarray[$i][0]="MIDDLE";
        $nameelement=~s/\,//g;
        $nameelement=~s/\.//g;
        $returnarray[$i][1]=$nameelement;
        $i++;
        $mnamematch++;
        next NAMEPARSE;
      }
    } elsif($i == 2) {
      # Test to see if third element
      # Must be middle if there since there are more than one elements after this
      # Middle Name
      $returnarray[$i][0]="MIDDLE";
      $nameelement=~s/\,//g;
      $nameelement=~s/\.//g;
      $returnarray[$i][1]=$nameelement;
      $i++;
      $mnamematch++;
      next NAMEPARSE;
    }
  }
  foreach $j (0...(scalar(@returnarray)-1)) { 
    $name{$returnarray[$j][0]} = $returnarray[$j][1]; 
  } 
  return (%name);
} # End ParseName

=head1 AUTHOR

Hugh Esco, C<< <hesco at campaignfoundations.com> >> and James Jones

=head1 BUGS

Please report any bugs or feature requests
to C<bug-lingua-en-nameparse-simple at
rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Lingua-EN-NameParse-Simple>.
I will be notified, and then you'll automatically be notified
of progress on your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Lingua::EN::NameParse::Simple


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Lingua-EN-NameParse-Simple>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/Lingua-EN-NameParse-Simple>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/Lingua-EN-NameParse-Simple>

=item * Search CPAN

L<http://search.cpan.org/dist/Lingua-EN-NameParse-Simple/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 COPYRIGHT & LICENSE

originally written as: 

parser.pm -- Parses a name into its constituent parts 
Copyright (C) 2004 by Hugh Esco, James Jones and the Georgia Green Party

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 dated
June, 1991 or at your option any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

A copy of the GNU General Public License is available in the
source tree; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

=cut

1; # End of Lingua::EN::NameParse::Simple

