class ref name: person
category-group: people
layer: 7
header file: z_person.h

synopsis.
The person_o class represents a person. This representation of a person attempts to disassociate from any context (such as an employee, patient, inmate, etc) - a person instance is simply a person. The characteristics of a person can be set by the single member function set_value() and obtained via the orthodox (ie base class) get() function. This class reflects its American roots as it has built into it the properties social_security_number, num_felonies, and num_misdemeanors". It provides start and end dates via the fields birth_date and death_date. The class worker_o is related to the person_o class, but a worker is not derived from a person, as you might expect. This is because of limitations in the orthodox implementation - sub-classes deeper than 1 are not supported by orthodox_o (eg, person_o is derived from orthodox_o, and worker_o is derived from orthodox_o, but if worker_o was to be derived from person_o, you could not create or access a "worker" database table via the orthodox framework (this is a limitation that hopefully will be remedied one day in the future).

description.
Unlike the business_o class. the person class has very few getter-setter functions. This is especially true for subtables. The subtables for person_o are the same as for a business: postal_address, phone_number, email_address, event, and extended_data - but adding an instance of one of these objects must be done via the base class function add_object(). This makes the person object more abstract, requiring more operational knowlege of the orthodox framework (which is a good thing to learn).

As an orthodox sub-class, the database schema string for a person looks like this:

columns
[
  <name        type qual nulls_ok is_uniq ref_table ref_column default check>
  <fname          char       40   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <mname          char       40   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <lname          char       40   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <generation     char        5   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <maiden_name    char       30   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <nickname       char       30   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <prefix         char       20   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <suffix         char       30   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <oname          char       80   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <ssno           char       12   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <sex            char        2   YES     NO      \"\"  \"\"  \"\"
  \" (sex = \\\"M\\\" or sex = \\\"F\\\" or sex = \\\"?\\\") \" >
  <race           smallint \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <father         int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <mother         int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <spouse         int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <cco_citizen    char        4   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <cco_current    char        4   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <cco_national   char        4   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <friendly       int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <birth_date     date     \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <death_date     date     \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <birth_place    char       40   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <death_place    char       40   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <curr_addr      int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <curr_phone     int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <lang0          int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <lang1          int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <lang2          int      \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <degree         varchar   160   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <awards         varchar   160   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <papers         varchar   240   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <is_married     char        2   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <education      varchar   240   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <is_married     char       2    YES     NO      \"\"  \"\"  \"\"  \"\" >
  <was_married char    2    YES     NO      \"\"  \"\"  \"\"  \"\" >
  <married_on     date     \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <indict_big     smallint   \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
  <indict_small   smallint \"\" YES     NO      \"\"  \"\"  \"\"  \"\" >
  <description    text     \"\"   YES     NO      \"\"  \"\"  \"\"  \"\" >
    ]
A person can and usually does have things such as a postal address, telephones, and e-mail addresses, so the following objects represent sub-tables of the person class (this is the same list as the business object; please see the discussion there for more details on subtables):

postal_address_o
phone_number_o
email_address_o
event_o
extended_data_o

Essentially, this object is simply a bucket to hold a person's information. The following table provides the accessor keyword (for get_value() and set_value()), and a description of the fields:

external name DB column name may dup? description
first_name fname person's [first] name
middle_name mname middle name
last_name lname last name (aka surname; family name)
generation generation ie, "Jr.", "Sr.", or Roman number ("IV"); etc.
maiden_name maiden_name for women
nickname nickname [self-explanatory field]
other_name oname any other name besides a nickname (such as an alias)
prefix prefix e.g., "Ms.", "Dr."
suffix suffix e.g., "Jr."
social_security_number ssno social security number (for Americans only)
sex sex a person's sex, represented as a 1-letter designator: M | F | B | ?
B - a name that can be of either sex;
? - the person's sex is unknown
note: the term "gender" was briefly implemented, until it was discovered that "sex" is the correct term.
race race this is an integer code. The values and semantics are unknown (probably needs to be developed).
father, mother, spouse father, mother, spouse values passed in to set these are numbers - ID values that reference other rows in the 'person' table (person.id).
citizenship cco_citizen the [primary] citizenship of the person. This is implemented as a code that references country.code
current_country cco_current the country code that the person currently resides in. This is implemented as a 3-character code that references country.code
nationality cco_national The country codee of the person's nationality (set at birth). This differs from citizen_code in that a person's current citizenship may differ from where he / she was born.
friendly friendly a subjective, numeric value indicating how friendly this person is. Interpretation is similar to "business.potent". Values range from 0 to 100.
birth_date birth_date birth date; the value of this field is a valid date format (ie, "mm/dd/yyyy")
death_date death_date death date (if applicable). Same format as "birth_date"
birth_place birth_place persons' birthplace (this is just a string, up to 40 characters)
death_place death_place where the person died (may be null)
unassigned_1 curr_addr YES current address: references the database table.field postal_address.ID
unassigned_2 curr_phone YES current phone: references the phone_number table
language_native lang0 the is the ISO 639-1 lanauage code. It must be an entry from the language table. This field is the person's "primary language".
language_second lang1 secondary language (3-letter ISO code)
language_other lang2 tertiary language (3-letter ISO code). A maximum of 3 languages is supported by this object's schema.
degrees degree any degrees the person has (free-form text up to 160 chars)
awards award any awards person has (free-form text up to 160 chars)
publications papers a list of publications the person has (free-form text; 240 chars max)
education education brief description of the person's education (free-form text; 240 chars max)
marital_status is_married M=Married, U=Unmarried, S=Separated
previous_marriage was_married the person been married previously [values: "Y", "N"]
marriage_date married_on date of [the last] marriage, if applicable
num_felonies indict_big the number of indicted felony (American-oriented) criminal charges. Default is 0.
num_misdemeanors indict_small the number of indicted misdemeanor (American-oriented) criminal charges. Default is 0.
description description person description. free-form text

The "may dup" [3rd] column represents database table ("person") columns that duplicate the functionality provided by subtables. If the row has a "YES" entry, you should avoid using it - the table field will [probably] be phased out. Use the orthodox_o base class member function add_object() to add a "sub-object" instead.

member functions (primary)

person_o()
SIGNATURE: person_o ()
SYNOPSIS: creates a person object, devoid of any data.
 

person_o(person_o)
SIGNATURE: person_o (const person_o &rhs)
SYNOPSIS: makes an exact copy of the "rhs" object.
TRAITS: this function is inline
 

operator = (person_o)
SIGNATURE: person_o &operator = (const person_o &rhs)
SYNOPSIS: copies exactly the RHS object ("rhs"); any previous contents are over-written.
RETURNS: reference [handle] to the current (left-hand side) object
 

destructor
SIGNATURE: ~person_o ()
SYNOPSIS:
'destroys' the object: all data fields are reset (to empty strings). This should be explicitly called only on pointers to computer objects created via "new".
 

person_o(person_o)
SIGNATURE: person_o (const string_o &s)
SYNOPSIS:
makes a new person object, assigning it the name 's'. The semantics of the assignment from a string variable is exactly that of person_o &operator = (const textstring_o &s).
 

bad_reference()
SIGNATURE: const person_o &bad_reference ()
SYNOPSIS:
This returns a reference to the standard "bad variable" for the class. It is used to check for errors by functions that return a reference and cannot set an external error flag, such as an assignment operator.
TRAITS: this is a static member function
 

clone()
SIGNATURE: person_o *clone () const
SYNOPSIS:
makes an exact copy of the person object. a pointer to the new object is returned. You must explicitly use delete to clean up the object after done with it:

person_o p ("Alfred E. Neuman");
person_o *my_clone = p.clone();
// use 'my_clone'
delete my_clone;

TRAITS: this function is inline
 

operator !=()
SIGNATURE: int operator != (const person_o &p) const
SYNOPSIS: [WIP]
TRAITS: this function is inline
 

operator ==()
SIGNATURE: int operator == (const person_o &p) const
SYNOPSIS: Compares 2 person objects to test for equality. Uses a variety of methods to make a positive ID.
DESCRIPTION:
This is the cop version of finding a person. We use the "id" field, if possible: 'id==0' means that it has not been set. If so, we move on to the social security number, then if either party's ss# has not been set, we can't use that, so we check the name+birthdate+birthplace; if everything fails, we give up and declare that we cannot positively ID the person and hence the objects are different
RETURNS:
0: the objects are different
1: the objects are equal
 

same_name()
SIGNATURE: int same_name (const person_o &that) const
SYNOPSIS: this is a relaxed version of the "==" operator. It checks only first and last names for a match.
RETURNS:
0: the object's names are different
1: the objects are [considered to be] the same
 

name()
SIGNATURE: const string_o name (boolean salute = FALSE, boolean title = FALSE, int *pi = NULL) const
SYNOPSIS: returns the name of the person. This is almost equivalent to get("full_name").
PARAMETERS

  • salute: [input] if TRUE, the returned string will include a "salutation" (Mr., Ms., or Mrs.) at the beginning of the string, if the object's name has been set, and the sex of the person can be determined. The default is FALSE - only the name (full name, first and last) is returned in the output variable.
  • title: if TRUE, and the person has a title, a ", [<title>]" will be appended, where <title> is the person's title
  • pi: [output] error indicator variable. values:
    0: successful
    zErr_CannotResolve: the sex of the person cannot be determined. Either it was not set, or the person's first name is androgynous, or it is not known if male or female (this flag is only applicable when salute = TRUE).
    zErr_Data_Corrupted: internal error - "sex" or "marital_status" variables not found. this should never happen, and is a panic situation
RETURNS:
[string]: person's name
[empty string]: if "", an error occurred
 

get_value()
SIGNATURE: const string_o &get_value (const string_o &, int *) const
SYNOPSIS: [WIP]
 

get_nth_xdata()
SIGNATURE: const xdata_o &get_nth_xdata (const string_o &, count_t, int *) const
SYNOPSIS: This function appears to be deleted.
 

get_nth_income()
SIGNATURE: const xdata_o &get_nth_income (count_t, int *) const
SYNOPSIS: This function appears to be deleted.
TRAITS: this function is inline
 

get_nth_status()
SIGNATURE: const xdata_o &get_nth_status (count_t, int *) const
SYNOPSIS: This function appears to be deleted.
TRAITS: this function is inline
 

get_nth_address()
SIGNATURE: const postal_address_o &get_nth_address (count_t, int *) const
SYNOPSIS: This function appears to be deleted.
 

get_nth_arpa()
SIGNATURE: const email_address_o &get_nth_arpa (count_t, int *) const
SYNOPSIS: This function appears to be deleted.
 

get_nth_phone()
SIGNATURE: const phone_number_o &get_nth_phone (count_t, int *) const
SYNOPSIS: This function appears to be deleted.
 

operator <<()
SIGNATURE: friend std::ostream &operator << (std::ostream &, const person_o &)
SYNOPSIS: prints out the person to the ostream
 

default_ccode()
SIGNATURE: const string_o &default_ccode()
SYNOPSIS: This function appears to be deleted.
TRAITS: this function is inline
 

reset()
SIGNATURE: int reset ()
SYNOPSIS: resets the object to its initial at-construction state. all data is wiped out.
 

add_address()
SIGNATURE: int add_address (const postal_address_o &)
SYNOPSIS: This function appears to be deleted.
 

add_event()
SIGNATURE: int add_event (const event_o &, int *)
SYNOPSIS: This function appears to be deleted.
 

add_income()
SIGNATURE: int add_income (const xdata_o &, int *)
SYNOPSIS: This function appears to be deleted.
 

add_status()
SIGNATURE: int add_status (const xdata_o &, int *)
SYNOPSIS: This function appears to be deleted.
 

operator =()
SIGNATURE: person_o &operator = (const textstring_o &s)
SYNOPSIS:
assigns a name to a person. The name should be in normal, colloquial format, eg, "John Hancock", "Dr. Hannibal Lecter", or "Mr. Howell, III". Some common prefixes (ie, salutation titles) are supported, primarily those in English and Spanish. However, given the vast number of titles and other such lexems that exist in the human idiom, many will be missed here. Thus, in parsing "Sultan Swing", "Sultan" will not be found in the list of titles, so it will be treated as a first name (which will not be found in the first_name table, by the way); likewise for Sir, Honorable, Sheikh, and most all non-English (with the exception of some Spanish) prefixes.
For such prefixes, It is highly recommended to use abbreviated form, eg, "Dr." (include the closing period) instead of "Doctor".
 

operator =()
SIGNATURE: person_o &operator = (const textstring_o &s)
SYNOPSIS: assigns a name to a person. The name should be in normal,
 

set_name()
SIGNATURE: int set_name (const string_o &s, const string_o &sloc = "ENG", int *pi = NULL)
SYNOPSIS:
This is a convenience function that is actually a simple wrapper around z_parse_person_name(). It sits between that subroutine and the operator = (textstring_o &) function in utility and complexity. The simple assignment operator does not allow defining a locale but is extremely easy to use. z_parse_person_name() lets you set the locale but you need to deal with many parameters. This function gives you the ease of use of the assignment operator, with the ability to control locale.
 

set_value()
SIGNATURE: int set_value (const string_o &snam, const string_o &sval, int *pi = NULL)
SYNOPSIS:
sets a property of the person, eg:

int ie0, ie1;
person_o hb;
ie0 = hb.set_value ("first_name",   "Ann", &ie1);
ie0 = hb.set_value ("last_name",    "Coulter", &ie1);
ie0 = hb.set_value ("sex",          "F", &ie1);
ie0 = hb.set_value ("friendly",     "-50", &ie1);
ie0 = hb.set_value ("birth_date",   "12/08/1961", &ie1);
ie0 = hb.set_value ("num_felonies", "5", &ie1);

PARAMETERS
  • snam: [input] the name of the item to set
  • sval: [input] the value of the item to set it to
  • pi: [output] error indicator variable. values:
    0: successful
    1: unknown keyword-name;
    2: internal error - problem setting the value;
    3: bad "social security number" format
TRAITS: the output error codes (for 'pi') are non-standard and will change soon
 

error_info()
SIGNATURE: string_o error_info () const
SYNOPSIS: this is an obscure, semi-internal function for analyzing errors
 

z_parse_person_name()
SIGNATURE: int z_parse_person_name (const string_o &s, string_o &fnam, string_o &mnam, string_o &lnam, string_o &pre, string_o &suf, char &sex, const string_o &the_locale = "", boolean do_dbfetch = TRUE, int *pi = NULL)
SYNOPSIS: Takes the full name of person, breaks up into its components
PARAMETERS

  • s: [input] a string containing the person's full name, first name first, last name at the end. It can contain prefixes (titles) and suffixes (more titles, degrees, honors, etc). A complex string can look like so:
    "Pres. Barack Hussein Obama, Esq."
  • fnam: [output] first name
  • mnam: [output] middle name
  • lnam: [output] last name
  • pre: [output] prefix (title)
  • suf: [output] suffix (eg, "Esq."; "III")
  • sex: [output] sex designator character; that is, the sex of the person, as a 1-character code: 'M': male; 'F': female; 'F': female; 'B': can be either male or female; '?': unknown; '-': this means no DB lookup, or DB is unavailable
  • the_locale: [input] the locale to use. Default value is "ENG" (ie English). Currently only "ENG" and "ESP" are supported.
  • do_dbfetch: [input] if TRUE, looks up the first name (if one is found) in the Z Directory GEO database (which must be open, available, and configured in order for the lookup to succeed.
  • pi: [output] error indicator variable. values:
    0: successful parse; no errors
    zErr_Param_NotSet: empty string provided (in 's')
    zErr_UnsupportedProto: unknown - unsupported locale
    zErr_NoMatch: first name not found in database (do-fetch case)
    zErr_DB_Cannot_Accesse: database is unavailable
DESCRIPTION:
This function is the workhorse of the assignment operator (person_o::operator = (string_o)) and set_name(). It takes a name like "John Hancock" and breaks it up into its constituent components pieces, eg "John" and "Hancock". If there is a database open and available with the Z Directory geo tables loaded, you can set 'do_dbfetch' to TRUE and look up the sex associated with the [first] name. All the output fields will be reset, that is set to empty strings ("") in all cases. Any data found will be then put into these variables. In the Hancock case, only variables 'fnam' and 'lnam' will be non-empty. An empty parameter means nothing was found for it.
RETURNS:
0: successful parse
-1: error, parsing failed
 

z_parse_person_title()
SIGNATURE: int z_parse_person_title (const string_o &s, const string_o &loca = "ENG", struct z_HBTitleData *hbt = NULL, char &sex, int *pi = NULL)
SYNOPSIS:
This looks for a keystring that prefixes a person's name, such as "Dr.", "Mrs.", "Capt", or "Prof.". It will also search for fully spelled-out keywords ("Doctor"; "Professor"). If one is found, it will return 0. It will also copy the information into the output parameter 'hbt' (which uses a specially designed structure specifically for this subroutine) if 'hbt' is not NULL.
PARAMETERS

  • s: [input] a string containing the title keystring to check, such as "Doctor", "Gov.", "Ms.", or "Trooper".
  • loca: [input] the locale to use. Default value is "ENG".
  • hbt: a pointer to a 'z_HBTitleData' (Human Bean Title Data) record. This can be NULL, in which case no information is returned (the return value can be used in and of itself). Otherwise, all structure elements will be copied into.
  • sex: [output] sex indicator character. if the gender can be determined from the title, this will be set (to 'M' or 'F'). If not, it is set to '?' (or possibly 'B').
  • pi: [output] error indicator flag. values:
    0: successful lookup
    zErr_Param_NotSet: empty string provided
    zErr_UnsupportedProto: unknown - unsupported locale
DESCRIPTION:
this subroutine was created to be subsidiary to z_parse_person_name(), but it is useful on its own. Although designed for many languages (locales), as of this writing (2013) only 2 are supported: "ENG" and "ESP" (for Spanish). Thus, title prefixes such as "Señor" or "Abogado" are handled. You can search all locales by specifying the reserved word "ALL" for the locale parameter ('loca'). In that case, all implemented locale sets will be searched, starting with English. You cannot control the order of the locales searched. The first item matching will be returned. A match exists if any of 3 fields are the same: the full name; the alternate name (used to "normalize" to English alphabet the full name, eg, "Senor" not "Señor"); and the abbreviation. For abbreviations, the terminating dot ('.') must be there, and is included in the result value. Thus, "Mr" is not an acceptable prefix but "Mr." is.
RETURNS:
0: found
1: not found
-1: error
 

limitations.
there are obviously several limitations to this object, as evident by its database schema: only 3 languages are maintained; dual nationality is not supported; ID is oriented towards the American model (a single number - "social security number"), etc.

history.

??? 08/18/1996: database table: added "?" to sex type;
??? 04/25/1997: database table: changed "char(1)" -> "char(2)" for
??? 12/22/1997: set_value(): added format checking for s.s. #
Mon 01/05/1998: check_format_ssno() made a public utility function
??? 03/23/1998: converted to using data-bag to hold values
??? 04/12/1998: zdb_fetch_person_byid() - now uses external ID, not ID
??? 07/03/1998: folding it into "z" directory
??? 07/13/1998: changed "serial" -> "int unique" (new orthodoxy)
??? 08/09/2002: problem between the line items "degree" & "awards"
Wed 08/27/2003: moved "person_o::name()" from inline [--GeG]
Thu 05/09/2013: fixes dumb errors in dbag string (add "\n" at e-o-line)
Thu 05/23/2013: added sub-table list (same as business object)
Mon 05/27/2013: 'person_map' cleanup: added father/mother/spouse
Thu 06/06/2013: overhaul of the main driver (mainly validation)
Thu 06/06/2013: started, canceled column name change (sex -> gender)
Wed 06/12/2013: created person_o::set_name()