//
// NameParser.m
// Port of Greg Miernicki's PHP NameParser
//
// Created by Mark Pemburn on 2/7/13.
// Copyright (c) 2013 Pemburnia LLC. All rights reserved.
//
#import "NameParser.h"
@implementation NameParser {
NSArray *prefixes;
NSArray *surnamePrefixes;
NSArray *suffixes;
}
@synthesize prefix, firstName, middleName, lastName, suffix;
- (id) initWithFullName: (NSString *) fullName
{
self = [super init];
if (self) {
prefixes = [[NSArray alloc] initWithObjects: @"sr", @"dr", @"doctor", @"miss", @"misses", @"mr", @"mister", @"mrs", @"ms", @"judge", @"sir", @"madam", @"madame", @"AB", @"2ndLt", @"Amn", @"1stLt", @"A1C", @"Capt", @"SrA", @"Maj", @"SSgt", @"LtCol", @"TSgt", @"Col", @"BrigGen", @"1stSgt", @"MajGen", @"SMSgt", @"LtGen", @"1stSgt", @"Gen", @"CMSgt", @"1stSgt", @"CCMSgt", @"CMSAF", @"PVT", @"2LT", @"PV2", @"1LT", @"PFC", @"CPT", @"SPC", @"MAJ", @"CPL", @"LTC", @"SGT", @"COL", @"SSG", @"BG", @"SFC", @"MG", @"MSG", @"LTG", @"1SGT", @"GEN", @"SGM", @"CSM", @"SMA", @"WO1", @"WO2", @"WO3", @"WO4", @"WO5", @"ENS", @"SA", @"LTJG", @"SN", @"LT", @"PO3", @"LCDR", @"PO2", @"CDR", @"PO1", @"CAPT", @"CPO", @"RADM(LH]", @"SCPO", @"RADM(UH]", @"MCPO", @"VADM", @"MCPOC", @"ADM", @"MPCO-CG", @"CWO-2", @"CWO-3", @"CWO-4", @"Pvt", @"2ndLt", @"PFC", @"1stLt", @"LCpl", @"Capt", @"Cpl", @"Maj", @"Sgt", @"LtCol", @"SSgt", @"Col", @"GySgt", @"BGen", @"MSgt", @"MajGen", @"1stSgt", @"LtGen", @"MGySgt", @"Gen", @"SgtMaj", @"SgtMajMC", @"WO-1", @"CWO-2", @"CWO-3", @"CWO-4", @"CWO-5", @"ENS", @"SA", @"LTJG", @"SN", @"LT", @"PO3", @"LCDR", @"PO2", @"CDR", @"PO1", @"CAPT", @"CPO", @"RDML", @"SCPO", @"RADM", @"MCPO", @"VADM", @"MCPON", @"ADM", @"FADM", @"WO1", @"CWO2", @"CWO3", @"CWO4", @"CWO5", nil];
surnamePrefixes = [[NSArray alloc] initWithObjects: @"bon", @"ben", @"bin", @"da", @"dal", @"de", @"del", @"der", @"de", @"e", @"la", @"le", @"lo", @"los", @"san", @"st", @"ste", @"van", @"vel", @"von", nil];
suffixes = [[NSArray alloc] initWithObjects: @"dds", @"esq", @"esquire", @"jr", @"sr", @"2", @"i", @"ii", @"iii", @"iv", @"v", @"clu", @"chfc", @"cfp", @"md", @"phd", nil];
[self parse: fullName];
}
return self;
}
- (void) parse: (NSString *) fullName
{
prefix = @"";
firstName = @"";
middleName = @"";
lastName = @"";
suffix = @"";
NSArray *nameParts = [[self pregReplace: fullName withString: @" " usingPattern: @"[ \t\n]+"] componentsSeparatedByString: @","];
int numPieces = [nameParts count];
switch (numPieces) {
case 1:
[self withoutComma: nameParts];
break;
default:
[self withComma: nameParts];
break;
}
}
- (void) withComma: (NSArray *)nameParts
{
int i, s;
NSString *current;
NSString *next;
int numPieces = [nameParts count];
if ([self inArray: suffixes find: [nameParts objectAtIndex: 1]]) {
NSArray *subPieces = [[self trim: [nameParts objectAtIndex: 0]] componentsSeparatedByString: @" "];
int numSubPieces = [subPieces count];
for (i = 0; i < numSubPieces; i++) {
current = [self trim: [subPieces objectAtIndex: i]];
if (i < (numSubPieces - 1)) {
next = [self trim: [subPieces objectAtIndex: i + 1]];;
} else {
next = @"";
}
if (i == 0 && [self inArray: prefixes find: current]) {
[self setPrefix: current];
continue;
}
if ([firstName isEqualToString: @""]) {
[self setFirstName: current];
continue;
}
if (i == numSubPieces - 1) {
[self setLastNameToCurrent: current];
continue;
}
if ([self inArray: surnamePrefixes find: current]) {
[self setLastNameToCurrent: current];
continue;
}
if ([next isEqualToString: @"y"] || [next isEqualToString: @"Y"]) {
[self setLastNameToCurrent: current];
continue;
}
if (![lastName isEqualToString: @""]) {
lastName = [NSString stringWithFormat: @"%@ %@", lastName, current];
continue;
}
[self setMiddleNameToCurrent: current];
}
suffix = [self trim: [nameParts objectAtIndex: 1]];
for (i = 2; i < numPieces; i++) {
suffix = [NSString stringWithFormat: @"%@, %@", suffix, [self trim: [nameParts objectAtIndex: 1]]];
}
} else {
NSArray *subPieces = [[self trim: [nameParts objectAtIndex: 1]] componentsSeparatedByString: @" "];
int numSubPieces = [subPieces count];
for (i = 0; i < numSubPieces; i++) {
current = [self trim: [subPieces objectAtIndex: i]];
if (i < (numSubPieces - 1)) {
next = [self trim: [subPieces objectAtIndex: i + 1]];;
} else {
next = @"";
}
if (i == 0 && [self inArray: prefixes find: current]) {
[self setPrefix: current];
continue;
}
if ([firstName isEqualToString: @""]) {
[self setFirstName: current];
continue;
}
if (i == numSubPieces - 2 && ![next isEqualToString: @""] && [self inArray: suffixes find: next]) {
[self setMiddleNameToCurrent: current];
suffix = [NSString stringWithFormat: @"%@", next];
break;
}
if (i == numSubPieces - 1 && [self inArray: suffixes find: current]) {
suffix = [NSString stringWithFormat: @"%@", current];
continue;
}
[self setMiddleNameToCurrent: current];
}
NSString *lastPart = [nameParts lastObject];
if (lastPart != nil && ![lastPart isEqualToString: @""]) {
if ([lastName isEqualToString: @""]) {
suffix = [NSString stringWithFormat: @"%@", lastPart];
for (s = 3; s < numPieces; s++) {
suffix = [NSString stringWithFormat: @", %@", [self trim: [nameParts objectAtIndex: s]]];
}
} else {
for (s = 2; s < numPieces; s++) {
suffix = [NSString stringWithFormat: @", %@", [self trim: [nameParts objectAtIndex: s]]];
}
}
}
lastName = [NSString stringWithFormat: @"%@", [nameParts objectAtIndex: 0]];
}
}
- (void) withoutComma: (NSArray *)nameParts
{
NSArray *subPieces = [[self trim: [nameParts objectAtIndex: 0]] componentsSeparatedByString: @" "];
int numSubPieces = [subPieces count];
int i;
NSString *current;
NSString *next;
for (i = 0; i < numSubPieces; i++) {
current = [self trim: [subPieces objectAtIndex: i]];
if (i < (numSubPieces - 1)) {
next = [self trim: [subPieces objectAtIndex: i + 1]];;
} else {
next = @"";
}
if (i == 0 && [self inArray: prefixes find: current]) {
[self setPrefix: current];
continue;
}
if ([firstName isEqualToString: @""]) {
[self setFirstName: current];
continue;
}
if (i == numSubPieces - 2 && ![next isEqualToString: @""] && [self inArray: suffixes find: next]) {
[self setLastNameToCurrent: current];
suffix = [NSString stringWithFormat: @"%@", next];
break;
}
if (i == numSubPieces - 1) {
[self setLastNameToCurrent: current];
continue;
}
if ([self inArray: surnamePrefixes find: current]) {
[self setLastNameToCurrent: current];
continue;
}
if ([next isEqualToString: @"y"] || [next isEqualToString: @"Y"]) {
[self setLastNameToCurrent: current];
continue;
}
if (![lastName isEqualToString: @""]) {
lastName = [NSString stringWithFormat: @"%@ %@", lastName, current];
continue;
}
[self setMiddleNameToCurrent: current];
}
}
- (void) setLastNameToCurrent: (NSString *)current
{
if (![lastName isEqualToString: @""]) {
lastName = [NSString stringWithFormat: @"%@ %@", lastName, current];
} else {
lastName = [NSString stringWithFormat: @"%@", current];
}
}
- (void) setMiddleNameToCurrent: (NSString *)current
{
if (![middleName isEqualToString: @""]) {
middleName = [NSString stringWithFormat: @"%@ %@", middleName, current];
} else {
middleName = [NSString stringWithFormat: @"%@", current];
}
}
- (BOOL) inArray: (NSArray *)haystack find: (NSString *)needle
{
needle = [[needle lowercaseString] stringByReplacingOccurrencesOfString: @"." withString: @""];
needle = [self trim: needle];
return [haystack containsObject: needle];
}
- (NSString *) pregReplace: (NSString *)string withString: (NSString *)replace usingPattern: (NSString *)pattern
{
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: pattern
options: NSRegularExpressionCaseInsensitive
error: &error];
NSString *modifiedString = [regex stringByReplacingMatchesInString: string
options: 0
range: NSMakeRange(0, [string length]) withTemplate: replace];
return modifiedString;
}
- (NSString *)trim: (NSString *)string
{
return [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
}
@end