class ref name: worker
category-group: people
layer: 11
header file: z_worker.h

synopsis.
The worker_o class is a large, involved class in the people group. It represents a person that has a relationship with a business. It ia superset of an employee, since it encompasses contractors, owners, directors, etc. The object is separate and distinct from the person , although highly dependent on it. The two objects work in tandem.

A worker object is a child of the orthodox_o class. Thus, a worker can be written to or retrieved from a database. This class stands apart from the other objects in the Z Directory in that the ID of a worker (and a person) is unique for each object instance. This means that copying a worker (and a person) results in a transfer of identity, leaving the copied object without a valid ID.

In order for the Z Directory business object to be able to exist in a database, all of its dependencies must be met. This means that the topology dataset needs to be loaded prior to saving a worker. The Z Directory topology dataset is normally done when the Z Directory is installed. The program using the worker object must be able to access this database, which can be on a different computer from the program. Basically the database must be accessible via the Z Directory components. A limitation is that the worker table must be in the same database as the other topology dataset. The ability to use tables in a different database from the table in question ("worker" table, in this case) is not yet available in the Z Directory.

There are some quirks that complicate the usage of a worker class object. Since the worker_o class works in conjunction with the business and person claases, usually these objects are required to co-exist with the worker object in order for the latter to do anything really useful. In fact, you usually need to set up "pools" - a set of businesses, workers, and people prior to using one of the many functions that operate on worker objects. Another complication involves IDs: one needs to ID a person (and business) object instance that a worker instance binds to. There are 2 groups of IDs: local (ie, the current object instance in the code) and remote (ie, the ID used in the object's associated database table and row).

description.
A business, in the Z Directory object world, knows nothing about its workers. The concept of a workforce "sits above" the business class. There is absolutely no mention of worker_o in its header file, z_business.h. Conceptually, a worker as an object is an associative array: (business)+(person). The worker class object always holds IDs to a person, boss, or business. Originally, pointers to other objects were used but that technique showed to have many problems and was quickly abandoned (the objects the pointers pointed to kept moving). With the worker_o class comes the associated "worker" table in the database. The table represents a person's job at a business. If a person worked at the same business more than once, there would be more than one entry. If a person had been employed at a corporation for 30 years, there would be 1 entry.

As an orthodox sub-class, the worker_o class has a database schema. The 'columns' section of this schema looks like this:

columns
[
  < name type qual nulls_ok is_uniq ref_table ref_column default check >
  < person              int       \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < business            int       \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < potential           int        3   YES NO  \"\"  \"\"  \"\"  \"\" >\
  < postal_address      int       \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < supervisor_id       int       \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < status              char        10 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < self_employed       char         2 YES NO  \"\"  \"\"  \"\"
  \"(self_employed = \\\"Y\\\" or self_employed = \\\"N\\\"
  or self_employed = \\\"?\\\")\"  >
  < start_rate          int       \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < end_rate            int       \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < time_unit           smallint  \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < extension           char        10 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < mail_stop           char        20 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < title               char        60 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < department          char        80 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < location            char        60 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < termination_reason  char        40 YES NO  \"\"  \"\"  \"\"  \"\"  >
  < description         text      \"\" YES NO  \"\"  \"\"  \"\"  \"\"  >
  < note                text      \"\" YES NO  \"\"  \"\"  \"\"  \"\"  > "
]
The Z Directory worker schema uses 2 sub-tables: phone_number and email_address. A notable aspect of the worker table is that it has several foreign keys:
column references
person person.id
business business.id
time_unit salary_code.id

getting and setting values.

there are two types of data that can be manipulated for a worker - properties, and items that can have more than one ocurrance (the same is true for the business_o class object). To retrieve a property value, use get_value(), and to set a value, use set_value(). To get an item of the latter type (a "multi-valued" item), use get_nth_value() or a specialization of this function such as get_nth_phone() or get_nth_arpa(). To add a new multi-valued item, use add_value(). This can be summarized in the following chart:

single-valued multi-valued
get get_value() get_nth_value()
set set_value()
add_value()
The list of properties ("single-valued items") are:
keyword DB column notes
found found
id id
id_person person
id_business business
id_location postal_address
id_boss supervisor_id
unassigned_0 position
unassigned_1 self_employed
t_start t_start
t_end t_end
start_rate start_rate
end_rate end_rate
pay_time_unit time_unit
unassigned_2 phone_number
extension extension
mail_stop mail_stop
title title
department department
location location
reason termination_reason
source source
what description
note note

The keywords for the multi-valued items are:

  • "email-address" (alias: "arpa-address"): for fetching or adding an e-mail address.

  • "phone-number": for fetching or adding a phone number.

  • "fax-number": this is treated just like "phone-number", the only difference being that the phone number is designated as a fax number.

loading from text.

A feature central to this object, and to business_o, is the ability to load an object from a block of text, or print out a block of text representing one or several worker objects. One can even save a set of workers immediately into a database in this way. The text must be in a specific, exact format. Here are some examples:

const char *worker_list =
"who:	Conan Barbarian\n\
	title: Manager\n\
	arpa: arnold@terminators.org,
		actorConan@holleywood-actors-guild.com\n\
	loc: Hyboria\n\
	Jenny ???\n\
		arpa: jenny.noname@ibm.net\n\
		loc: New York\n\
		phone: (900) 867-5309\n\
		note: she never answers";
Briefly, the format for printing a list of employees (or other worker types) is heavily based on the TAB character (ascii 0x8; embedded in the string above). A list of 1 or more workers is started with the keystring "who:", followed by a tab, followed by the person's name (first, ie given name is first). Two tabs following a newline denotes that the person's information block is continuing. To start another person's "information block", the syntax is a single tab after a newline, then the person's name (and of course, then a newline).

The example shows the 3 question marks ??? which is used as a placeholder for either a first name or a last (family) name which is unknown.

IDs and the database.

It is important to distinguish the external IDs from the internal IDs when working with the worker object. As explained in the orthodox [base] class , IDs are such a complicated affair that orthodox subclasses even have an object that manages IDs. In a nutshell, one must remmber to use the external IDs (via orthodox_o::externID() and set_externID()) when accessing the database, and regular IDs (orthodox_o::ID(), orthodox_o::set_ID()) when using only a local dataset (a "pool").

poolside searches.

A small set of subroutines, starting with "z_poolsearch_find".., are provided as an easy way to find a specific worker or person object matching a criteria. These are applied to a pool of worker objects and its matching pool of people, usually after populating these pools from a database lookup such as zdb_fetch_workers(). These routines are small, simple shortcuts to writing your own loops, and include:

  • z_poolsearch_findworker_byperson() - finds a worker object given his or her corresponding person object;
  • z_poolsearch_findperson_byworker() - the inverse of the previous function: it finds a person object given his or her corresponding worker object;
  • z_poolsearch_findworker_byemail() - looks up a worker by a given e-mail (which is loaded into an e-mail address object);
  • z_poolsearch_findworker_byphone() - looks up a worker by a given telephone number (which is loaded into a phone number object).
All of these routines have the same structure, with similar return values and parameter lists. If no matching object is found, a "bad reference" object [handle] is returned (either worker_o::bad_reference() or person_o::bad_reference()). The parameter list consists of [a reference to] the object to be searched for; the pool of workers / people (a vlist_o set); an output parameter that is the index number into the pool representing the position of the found object in the pool; and an integer output parameter that is 0 if a matching item was found.

member functions (primary)

worker_o()
SIGNATURE: worker_o ()
SYNOPSIS: creates a worker object, devoid of any data. No IDs are set.
 

worker_o(worker_o)
SIGNATURE: worker_o (const worker_o &rhs)
SYNOPSIS: makes a copy of the object 'rhs'.
DESCRIPTION:
the pointers to person, boss, and business are simply copied. No new instances are allocated - in that sense, this copy operation does not do a very deep copy. It is up to the application to manage the actual record space of the objects this object refers to. Just like with 'person' and 'business', the ID of a workser record that gets copied gets transferred to the recipient.
 

worker_o(<args>)
SIGNATURE: worker_o (const rec_dbag_o &bag)
SYNOPSIS: creates a worker object. The properties of the worker are set from the contents of 'bag'.
 

worker_o(<args>)
SIGNATURE: worker_o (const business_o &b, const person_o &p)
SYNOPSIS: creates a worker object.
 

destructor
SIGNATURE: ~worker_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".
TRAITS: this is a virtual function (always, as usual)
 

operator = (worker_o)
SIGNATURE: const worker_o &operator = (const worker_o &rhs)
SYNOPSIS:
copies the RHS object ('rhs'); any previous contents are over-written. See the copy constructor for the rules on how IDs are handled in a copy operation.
RETURNS: reference [handle] to the current (left-hand side) object
 

operator = (worker_o)
SIGNATURE: orthodox_o &operator = (const rec_dbag_o &bag)
SYNOPSIS: [WIP]
 

clone()
SIGNATURE: worker_o *clone () const
SYNOPSIS:
this function allocates a new worker object (via "new") and makes an exact copy of the current object. The ID of the new object (in the base class, orthodox_o) is invalidated (there can be only 1 actual, representing ID).
 

bad_reference()
SIGNATURE: worker_o &bad_reference ()
SYNOPSIS:
returns the "bad reference" - standard Z Directory "orthodox" construct, used for functions that return a reference. The return address of the object represents a singleton "bad" object, and that the function returning this reference failed.
TRAITS: this isd a static member function - it takes no specific object instance to invoke it
 

std::ostream <<()
SIGNATURE: std::ostream &operator << (std::ostream &o, const worker_o &w)
SYNOPSIS:
"prints" the worker object to the ostream variable 'o'. Print operations are forwarded to the person_o class (which prints the person's name).
TRAITS: this function is a friend of the worker_o class
 

operator !=()
SIGNATURE: boolean operator != (const worker_o &that) const
SYNOPSIS: compares to worker objects, tests for inequality
DESCRIPTION: this operator compares the current worker object to 'that'. It is the converse of "::operator == (that)"
RETURNS:
1: the workers are different
0: the workers are equivalent
 

operator ==()
SIGNATURE: boolean operator == (const worker_o &) const
SYNOPSIS:
compares to worker objects. The objects are equal if (a) their object IDs are equal, or (b) if the business and person objects (referenced by the current object) are the same.
RETURNS:
1: the workers are equivalent
0: the workers are different
 

person()
SIGNATURE: const person_o &person (int *) const
SYNOPSIS: [WIP]
 

business()
SIGNATURE: const business_o &business (int *) const
SYNOPSIS: [WIP]
 

boss()
SIGNATURE: const person_o &boss (int *) const
SYNOPSIS: [WIP]
 

person_ID()
SIGNATURE: count_t person_ID (int *) const
SYNOPSIS: [WIP]
 

business_ID()
SIGNATURE: count_t business_ID (int *) const
SYNOPSIS: [WIP]
 

boss_ID()
SIGNATURE: count_t boss_ID (int *) const
SYNOPSIS: [WIP]
 

OID_person()
SIGNATURE: const simpid_o &OID_person (int *pi = NULL) const
SYNOPSIS: returns the [entire] object ID of the person
TRAITS: an inline function.
 

OID_biz()
SIGNATURE: const simpid_o &OID_biz (int *pi = NULL) const
SYNOPSIS: returns the [entire] object ID of the business
TRAITS: an inline function.
 

OID_boss()
SIGNATURE: const simpid_o &OID_boss (int *pi = NULL) const
SYNOPSIS: returns the [entire] object ID of the boss
TRAITS: an inline function.
 

boss_name()
SIGNATURE: string_o boss_name () const
SYNOPSIS: [WIP]
 

fmterr()
SIGNATURE: const biz_fmterr_o &fmterr () const
SYNOPSIS: [WIP]
 

set_personID()
SIGNATURE: int set_personID (const simpid_o &id, boolean islocal = FALSE)
SYNOPSIS: the ID of the person, given as a "simple ID object"
PARAMETERS

  • id: the ID
  • islocal: if FALSE, use the id found in the database. if TRUE, look up the business in the local set of business objects
 

set_personID()
SIGNATURE: int set_personID (count_t x, boolean islocal = FALSE)
SYNOPSIS: [WIP]
PARAMETERS

  • id: the ID
  • islocal: if FALSE, use the id found in the database. if TRUE, look up the business in the local set of business objects
 

set_businessID()
SIGNATURE: int set_businessID (const simpid_o &id, boolean islocal = FALSE)
SYNOPSIS: [WIP]
PARAMETERS

  • id: the ID
  • islocal: if FALSE, use the id found in the database. if TRUE, look up the business in the local set of business objects
 

set_businessID()
SIGNATURE: int set_businessID (count_t x, boolean islocal = FALSE)
SYNOPSIS: [WIP]
PARAMETERS

  • id: the ID
  • islocal: if FALSE, use the id found in the database. if TRUE, look up the business in the local set of business objects
 

set_person()
SIGNATURE: int set_person (const person_o &p, int *pi, boolean = FALSE)
SYNOPSIS: [WIP]
 

set_boss()
SIGNATURE: int set_boss (const person_o &p, int *pi, boolean = FALSE)
SYNOPSIS: [WIP]
 

set_bossname()
SIGNATURE: int set_bossname (const string_o &nam)
SYNOPSIS: [WIP]
 

set_business()
SIGNATURE: int set_business (const business_o &, int *, boolean = FALSE)
SYNOPSIS: [WIP]
 

set_business_pool()
SIGNATURE: int set_business_pool (business_list *bp)
SYNOPSIS: [WIP]
 

set_population_pool()
SIGNATURE: int set_population_pool (person_list *pp)
SYNOPSIS: [WIP]
 

reset()
SIGNATURE: int reset ()
SYNOPSIS: [WIP]
 

get_value()
SIGNATURE: const string_o get_value (const string_o &nam, int *pi) const
SYNOPSIS: this returns the first item in a multi-valued [list] item
PARAMETERS

  • nam: the keyword for the item desired. See the properties keyword list (in the main discussion on this page) for a list of valid keywords.
  • pi: error indicator variable. The values this variable can have:
    0: ok; item successfully retrieved
    zErr_Param_BadVal: illegal name code
 

get_nth_value()
SIGNATURE: const string_o get_nth_value (const string_o &kw, count_t n, int *pi) const
SYNOPSIS: gets the nth item 'kw' from the object.
PARAMETERS

  • s: keyword for the item desired
  • n: index number of the item desired. Value of 'n' for the first item is 0.
  • pi: error indicator variable. The values this variable can have:
    0: ok, success
    zErr_Param_BadVal: unknown/illegal keyword submitted
    zErr_Param_OuttaBounds: "n" > (# items requested)
    3: internet address not set (internal error?)
DESCRIPTION:
valid keystrings ('kw'):
"email-address" (also: "arpa-address")
"phone-number"
"fax-number": this is almost identical to "phone-number". The only difference is internally marking the phone as of type fax.
 

get_nth_arpa()
SIGNATURE: const email_address_o &get_nth_arpa (count_t idx, int *pi) const
SYNOPSIS: gets the e-mail address of the worker referenced by index value 'idx'.
 

get_nth_phone()
SIGNATURE: const phone_number_o &get_nth_phone (count_t idx, int *pi) const
SYNOPSIS: gets the phone number of the worker referenced by index value 'idx'.
 

set_value()
SIGNATURE: int set_value (const string_o &nam, const string_o &val, int *pi = NULL)
SYNOPSIS:
Use this member function to set the values for properties of a worker: title, department, location, note, and many more.
PARAMETERS

  • nam: keyword for the item to set
  • val: Value to set the item to (in its string form)
  • pi: error indicator variable. The values this variable can have:
    0: ok, success
    1: illegal name code
    2: [phone] "extension" not a number
    3: internal inconsistency (check ename->name map)
DESCRIPTION:
This function is a sibling of add_value(), but is targeted for non-repeatable items - the "properties" of a worker.
 

add_value()
SIGNATURE: int add_value (const string_o &nam, const string_o &val, int *pi = NULL)
SYNOPSIS:
This member function is the equivalent of the business object put_value() and is used to add items specific to a worker (that is, not the person, but specifically that of a worker). It is used for repeatable items: e-mail addresses and phone numbers.
PARAMETERS

  • nam: keyword for the item to add. its values can be:
    "email-address" (alternate: "arpa-address")
    "phone-number"
    "fax-number"
  • val: value of the object to add (in string form)
  • pi: error indicator variable. The values this variable can have:
    0: successfully added
    1: illegal name code
    2: bad e-mail address format
    3: bad phone number given
    4: error in adding e-mail address
    5: error in adding the phone number
TRAITS:
it is unfortunate that worker_o::add_value() is functionally equivalent to business_o::put_value(). One of the names will be changed to match that of the other one day. Beware.
 

update_nth_value()
SIGNATURE: int update_nth_value (const string_o &key, const string_o &val, count_t n, int *pi = NULL) const
SYNOPSIS:
update the nth 'key' item. This will search for the given object, and if it exists, update its value. If the contents of 'val' is empty, the item will be deleted. There must be at least 'n' objects of the type designated by 'key' in order for this function to succeed. It is the application's responsibility to ensure the correct item is deleted; ie, the application must know (or figure out) the ordering of the objects (this can be done by calls to get_nth_value()).
PARAMETERS

  • key: the keyword for the item to update. its values can be:
    "email-address" (alternate: "arpa-address")
    "phone-number"
    "fax-number"
  • val: value of the object to add (in string form)
  • n: index into the list of objects of type 'key'. The first item is represented by index value of 0. If n' is negative, or exceeds the number of objects, the function call will fail and -1 is returned.
  • pi: error indicator variable. The values this variable can have:
    0: successfully updated;
    zErr_Index_OutofBounds: 'n' value invalid
    zErr_Param_NotSet: 'key' is an empty string;
    zErr_Param_BadVal: 'key' value is not valid;
    zErr_Param_BadFormat: the value in the string 'val' does not represent a valid object. For example, if 'key' is "email-address", perhaps there is no '@' in the string; or if 'key' is "phone-number" and 'val' contains letters or is a string that is [clearly] not a phone number.
    zErr_NotSupported: this value indicates an object delete was attempted, but the function does not provide for it. As of this writing (July 2013), object deletion has not been implemented.
RETURNS:
0: all ok
-1: error
TRAITS: [July 2013] currently deleting an object (by supplying an empty string into 'val') has not been implemented (INCOMPLETE!).
 

store_fetch()
SIGNATURE: int store_fetch (const string_o &wc = "", int *pi = NULL)
SYNOPSIS: this retrieves an existing worker from the database. it uses an optional "where clause", stored in input variable 'wc'.
DESCRIPTION:
this function redefines the base classes's function. It is necessary in order to synchronize the values for the business and person records with internal ID objects - that is, the values in the ["external"] IDs from the database are saved to the ID objects immediately after the orthodox_o store_fetch() is executed.
 

store_add()
SIGNATURE: int store_add (int *pi = NULL)
SYNOPSIS: this adds a new worker into the database.
DESCRIPTION:
This is not a regular orthodox "store_add()" member function. Calling this function will add a row to the "worker" tabled, and it will also create a new row in the "person" table.
 

store_addboss()
SIGNATURE: int store_addboss (const person_o &p, boolean udb = TRUE, int *pi = NULL)
SYNOPSIS:
this updates the value of the worker's boss ID to p's ID. If the second parameter ('udb') is set to TRUE (by default it is so), the value of the boss ID in the database image of the object is also set to this ID value.
The external ID of 'p' must be set beforehand in order for this function call to succeed.
PARAMETERS

  • p: a reference (aka "handle") to the person object that is the boss of the current worker object.
  • udb: if TRUE, the database image of the worker object is also updated. If FALSE, only the local variable's ID is affected.
  • pi: [output] error indicator variable. The values this variable can have are:
    0: ok, successful record update
    zErr_DB_Cannot_Access: 'check_store()' failed
    [n > 0]: any other error code comes from dbbi_o::exec_sql() (which see)
 

sync_DBtoID()
SIGNATURE: int sync_DBtoID ()
SYNOPSIS: this function copies ID info to local internal variables
DESCRIPTION:
this function maps internal column values like "person" and "business" to internal variables such as 'id_person' and 'id_boss', and 'id_biz'.
This function could be private, but subroutines such as zdb_fetch_workers() need it. They could (should?) declare them friends of worker_o, but in this case, have been made public.
TRAITS: not intended for public consumption
 

master_population_pool()
SIGNATURE: person_list &master_population_pool ()
SYNOPSIS: [WIP]
TRAITS: static member function.
 

master_business_pool()
SIGNATURE: business_list &master_business_pool ()
SYNOPSIS: [WIP]
TRAITS: static member function.
 

set_master_population_pool()
SIGNATURE: int set_master_population_pool (person_list *)
SYNOPSIS: [WIP]
TRAITS: static member function.
 

set_master_business_pool()
SIGNATURE: int set_master_business_pool (business_list *)
SYNOPSIS: [WIP]
TRAITS: static member function.
 

numparse_errors_allowed()
SIGNATURE: count_t numparse_errors_allowed ()
SYNOPSIS: [WIP]
TRAITS: static member function.
 

numparse_errors_exceeded()
SIGNATURE: boolean numparse_errors_exceeded ()
SYNOPSIS: [WIP]
TRAITS: static member function.
 

set_numparse_errors_allowed()
SIGNATURE: int set_numparse_errors_allowed (count_t)
SYNOPSIS: [WIP]
TRAITS: static member function.
 

incr_numparse_errors()
SIGNATURE: int incr_numparse_errors ()
SYNOPSIS: [WIP]
TRAITS: static member function.
 

clear_numparse_errors()
SIGNATURE: int clear_numparse_errors ()
SYNOPSIS: [WIP]
TRAITS: static member function.
 

zdb_store_workers()
SIGNATURE: int zdb_store_workers (list_o<worker_o> &wg, list_o<person_o>&pg, list_o<business_o>&bg, boolean replace = FALSE, int *pi = NULL)
SYNOPSIS: saves each worker in the set of workers 'wg' to the database.
PARAMETERS

  • wg: a list of worker records (worker_o). This is typically implemented as a vlist_o
  • pg: a list of person records (person_o). This is typically implemented as a vlist_o
  • bg: a list of business records (business_o). This is typically implemented as a vlist_o
  • replace: if TRUE, prior to doing the add, any worker and person matching records are first deleted. This ensures that there are no duplicate records. The default is FALSE.
  • pi: error indicator variable. The values this variable can have are the same as (originate from) worker_o::store_add() (which see).
DESCRIPTION:
this subroutine iterates through 'wg' and adds each worker-person record pair into the database. If 'replace' is TRUE, any existing records matching those in 'wg' or 'pg' are deleted first. Note that all 3 sets of data are required as input parameters - the list of workers, people, and buisnesses (thus this routine can accomodate a multi-business set, each group of workers saved to their corresponding business).
TRAITS: this function is separate from the class worker_o (ie, global scope)
 

z_get_nth_worker()
SIGNATURE: const worker_o &z_get_nth_worker (const business_o &b, count_t n, int * = NULL)
SYNOPSIS: retrieves the nth worker object in the master-global pool of workers.
TRAITS:
this function is separate from the class worker_o (ie, global scope). It is of dubious usefulness and is probably going to go away.
 

zdb_fetchworker_byname()
SIGNATURE: int zdb_fetchworker_byname (business_o &b, worker_o &w, person_o &p, const string_o &biznam, const string_o &whonam, int *pi = NULL)
SYNOPSIS: retrieves a worker object-instance from a database, along with the corresponding business and person objects (if found).
DESCRIPTION:
This will retrieve either 0 or 1 sets of data: the business, the person, and the worker constitute a set. With this function you can look for a person who works for a specific company, or any person with a worker record. There can be more than one person ("worker") that match the criteria - if so, the first record set found is returned. Usage:
Put the name of the businss in 'bizname', and the name of the person in 'whoname'. The first matching record will be returned (if 1+ matches are found). If there are no matches, 1 is returned and the parameters ('b', 'w', 'p') are unchanged. . You can leave either of the search filter strings to empty (""). Doing so "wildcards" it:

  • zdb_fetchworker_byname(b,w,p,"", "John Deere"); - returns the first worker named "John Deere" (of any business)
  • zdb_fetchworker_byname(b,w,p,"XYZ Corp", ""); - returns the first worker found at XYZ Corp.
  • zdb_fetchworker_byname(b, w, p, "WJM-TV", "Mary Tyler Moore"); - returns the business "WJM-TV" and the person and worker object instances for "Mary Tyler Moore" (if found).

RETURNS:
0: object set found and loaded
1: no match
TRAITS: this function is a friend of class worker_o. It was written on Monday, June 10, 2013.
 

zdb_fetch_worker()
SIGNATURE: int zdb_fetch_worker (worker_o &w, const business_o &b, person_o &p, int *pi)
SYNOPSIS: fetches (looks up) a worker, given a business and person.
DESCRIPTION:
this routine searches for a worker record, and if found, loads the worker's info, including phones and e-mail addresses. Usage:
Load the ID of the business, or name (if using name, make sure the ID is 0), into the business object.
RETURNS:
0: all ok
1: no match
-1: error
TRAITS: [2013] THIS FUNCTION IS CURRENTLY BROKEN. IT IS UNAVAILABLE
 

zdb_fetch_workers()
SIGNATURE: int zdb_fetch_workers (const business_o &b, list_o<worker_o> &wlist, list_o<person_o> &plist, int *pi = NULL)
SYNOPSIS:
This subroutine retrieves all the workers for a specific business. The business is identified by its ID, which must be stored in input variable 'b'. The ID must be that used within the database, not any local pool ID.
DESCRIPTION:
this subroutine is an all-or-nothing method to retrieve a group of worker objects and the associated business. There is another subroutine with the same name, zdb_fetch_workers(), which has an additional string parameter that can be used to add a filter to the set of workers retrieved. The list of workers would then have to be iterated to retrieve individual worker object instances. Note that along with the worker objects, the corresponding person objects is fetched and put into 'plist'. The ordering of 'wlist' and 'plist' is usually the same, that is, the first worker instance of 'wlist' maps to the first person instance of 'plist' and so on, but this is not guaranteed - you should search 'plist' by ID (obtained via worker_o::person()).
RETURNS:
0: success; got at least 1 worker
1: no match; nobody found
-1: error occurred
TRAITS: this subroutine is separate from the class worker_o (ie, global scope)
 

zdb_fetch_workers()
SIGNATURE: int zdb_fetch_workers (const business_o &b, list_o<worker_o> &wlist, list_o SYNOPSIS:
This subroutine is exactly analogous in behaviour and input-output values to the sibling subroutine of the same name (see above) without the input parameter 'squery'. This 4th parameter is inserted into the "where clause" for the worker table, and can be used to limit the results. It unfortunately cannot be applied to the person table, so you cannot retrieve, say, all the employees named Bob.
TRAITS: this subroutine is separate from the class worker_o (ie, global scope)
 

z_merge_worker_into_population()
SIGNATURE: int z_merge_worker_into_population (list_o &workers, list_o &population, worker_o &new_w, person_o &new_p, person_o &new_b, worker_o **w, person_o **p, person_o **m, int *pi)
SYNOPSIS:
This routine adds a worker, specified by the input parameter 'new_w', into the labor pool. It assumes the caller-client application has set up the 'person' ID. This routine will allocate new records for the worker, person and finally the boss, if any.
DESCRIPTION:
This function clearly has a horribly long function signiture. This is unavoidable due to the nature of the worker object and behavior of IDs (simpid_o). The first set of parameters are references to the pools ('workers', 'population'). The next set of parameters are the inputs: 'new_w', 'new_p', and 'new_b'. The next set of parameters are outputs - pass the address of pointers for the resultant worker/person/boss. These last pointers can be NULL (if you are not interested in the results).
The reason the set of [output] pointers are included, as opposed to using the set of [input] references, is that the objects are copied when added into the pools. The object IDs itare unique to an object, and would be different for the set of [input] references (a better explanation is pending).
If there is "boss data", that is, if the first name and last name fields of 'new_b' are set (ie, return non-empty strings), it is assumed that 'new_b' is a valid handle and that variable is made to be the boss of 'new_w' (via set_boss() function).
If you want to add a new worker instance to the database, you must call this function prior (see usage notes) to first incorate the worker into a labor pool.
TRAITS:
this function is separate from the class worker_o (ie, it has global scope). It is a very important part of adding a worker into the database.
 

z_biz_n_workers_to_strblock()
SIGNATURE: int z_biz_n_workers_to_strblock (const business_o &b, vlist_o<worker_o> &wg, string_o &s, int *)
SYNOPSIS:
this formats the business 'b' to a string. It inserts the given group of workers ('wg') into the business's keyword block. The resultant text is put into output parameter 's'.
DESCRIPTION:
this member functino is a glorified 'business_o::print()' function. Since workers ("employees") are a distinct, separate class from the business class, and sitting in a different layer altogether, a separate suboutine apart from the class business_o is required. Note that there is no check to ensure that the worker objects of 'wg' really belong to the business (liberty vs. slavery?).
TRAITS: this function is separate from the class worker_o (ie, it has global scope)
 

z_workers_to_strblock()
SIGNATURE: int z_workers_to_strblock (const business_o &, vlist_o<worker_o> &, string_o &, int *)
SYNOPSIS: [WIP]
TRAITS: this function is separate from the class worker_o (ie, it has global scope)
 

z_takeout_worker()
SIGNATURE: int z_takeout_worker (const simpid_o &id, list_o &workpool, list_o &pop, worker_o &w, person_o &p, int *pi = NULL)
DESCRIPTION:
this removes a worker from a pool, if one is found whose ID matches that of 'id'. The worker and person (objects) are removed from their respective pools.
TRAITS: this function is separate from worker_o (global scope)
 

z_takeout_nth_worker()
SIGNATURE: int z_takeout_nth_worker (count_t idx, list_o &workers, list_o &pop, worker_o &w, person_o &p, int *pi = NULL)
TRAITS: this function is separate from worker_o (global scope)
 

zdb_fetch_business_by_worker()
SIGNATURE: int zdb_fetch_business_by_worker (business_o &b, worker_o &w, person_o &p, const string_o &s, int *pi = NULL)
SYNOPSIS: [WIP]
TRAITS: this function is separate from the class worker_o (ie, it has global scope)
 

z_extract_biz_whoblock()
SIGNATURE: int z_extract_biz_whoblock (const string_o &sin, string_o &sot, int *pi)
SYNOPSIS:
this searches for and copies the "who" section out of a block of text. The source text is in the first parameter, string variable 'sin', and the extracted - copied text is in 'sot'.
PARAMETERS

  • sin: a text string that is expected to contain a multi-line formatted block of "business data".
  • sot: the text copied from 'sin' containing the list of people
  • pi: error indicator variable. The values this variable can have are:
    0: ok, success
    1: ..
    2: to [TAB] found after "who:" keystring
DESCRIPTION:
the block of text that is intended to be processed by this function is a "business data" block. Within this block lies the list of workers for that business (the "who block"). Thus, given this:
start:	1990
popu:	940
phone:	+1 (800) 607-9546
www:	www.documentum.com
who:	Peta Adamson
		arpa: peta.adamson@documentum.com
		what: manages European user group
	Barry Solberg
		arpa: barry.solberg@documentum.com
	Patricia Menchaca
		title: Director
		dept: Investor Relations
arpa:	support@documentum.com {note: support}
summ:	computer sofware document management system
note:	1,500 clients; including Delta, Lockheed Martin,
	US Airways, Bechtel, Raytheon Engineering, Ford,
	Honda, Peugeot, Renault, Toyota, Volkswagen..
The text that is copied to 'sot' is:
Peta Adamson
	arpa: peta.adamson@documentum.com
	what: manages European user group
Barry Solberg
	arpa: barry.solberg@documentum.com
Patricia Menchaca
	title: Director
	dept: Investor Relations
That is, within a possibly very large multi-line block of formatted data pertaining to a specific bueiness, this subroutine culls out all the text irrelevant to processing employees. It also removes the "who:" keyword and excises a leading tab from each line, so that a block of text representing a single person starts a new line.
This function fetches the data that can be fed directly into z_strblock_to_workers().
TRAITS: this function is separate from the class worker_o (ie, it has global scope)
 

z_strblock_to_workers()
SIGNATURE: int z_strblock_to_workers (const string_o &sin, const business_o &b, vlist_o &workers, vlist_o &population, int *pi, string_o &errs)
SYNOPSIS:
This subroutine reads a [multi-line] block of text representing 0 or more workers, and maps the text into data representing those workers. The output data consists of a set of worker objects that get saved into the container 'population'. This subroutine works in conjunction with z_extract_biz_whoblock(), which prepares the input string it requires.
PARAMETERS

  • sin: the text string to be parsed and used as input data to this routine
  • b: the business object-entity for these workers
  • workers:
  • population:
  • pi: parsing liniency flag & error indicator variable. On the input side, the values this variable can have is 0 or 1: set it to 0 for "loose parsing mode" and to 1 for "strict parsing mode" (as discussed here).
    On the output side, the values this variable can have are:
    0: ok, success
    1: "population" pointer not set;
    2: internal problem..
    3: problem while trying to add works-for record
    4: worker error object not initialized
  • errs: a string containing a concatenation of messages - all errors that ocurred during parsing (if any).
DESCRIPTION:
This subroutine is often called in a loop, such as by an application processing a file containing a list of businesses, each possibly containing a list of employees. The first parameter, 'sbig', has the next string to process. The objects that are generated are saved into the container specified by the 3rd parameter to this function, 'population'. There is no need to worry about memory allocation as the worker objects are copied internally inside this call and put into 'population', which manages the objects in its collection. A singleton, global parameter container variable p_all_workers is provided as a convenience for the application to use as the variable for 'population'.
RETURNS:
0: successful parse; more text remains
1: successful parse; e-o-input -1: error occured (see 'pie')
TRAITS: this function is separate from the class worker_o (ie, of global scope, not a member function)
 

z_migrate_workers()
SIGNATURE: int z_migrate_workers (vlist_o<worker_o> &workgroup, const business_o &old_biz, const business_o &new_biz, const boolean stomp_onall = FALSE, int *pi = NULL)
SYNOPSIS:
move (migrate) all workers in 'workgroup' that belonged to 'old_biz' to a new business, 'new_biz'. This subroutine will change the internal ID values for the object (ie, 'id_biz'), but will not modify the database values of the worker's boss IDs.
PARAMETERS

  • workgroup: the list of people (ie person_o instances). This represents the universe of workers that this subroutine can draw worker_o records.
  • old_biz: the business that is to be searched for. Any worker objects that refer to this business will have their ID objects reset to point to that new business (given by 'new_biz')
  • new_biz: the business is to used as a replacement for 'old_biz'. Only the object ID is used here.
  • stomp_onall: if TRUE, 'old_biz' is ignored. It is assumed that every worker in 'workgroup' belongs to the old business ('old_biz'). Thus, each worker object in the list will have its ID object updated. If FALSE (the default), only those workers whose business ID matches that of 'old_biz' will have their business IDs updated.
  • pi: [output] error indicator variable.
TRAITS: this function is separate from the class worker_o (ie, it has global scope)
 

z_setworkers_bosses()
SIGNATURE: int z_setworkers_bosses (vlist_o<worker_o> &workers, person_list &people, const boolean db_too = TRUE, int *pi = NULL)
SYNOPSIS:
this syncronizes the workers with the bosses. This subroutine can be useful when a new population set is introduced, or the person objects have had their IDs modified. Since the name of a worker's boss is cached in the each worker object when the boss is set (or reset), this name is used to look up the person record in the given population.
The boss object ID is updated if it has changed; if 'db_too' is TRUE, the boss ID values in the database image of each worker record is also updated.
TRAITS: this function is separate from the class worker_o (ie, of global scope - not a member function)
 

z_setworkers_business()
SIGNATURE: int z_setworkers_business (vlist_o &workers, const business_o &b, const boolean do_db, int *pi = NULL)
SYNOPSIS: set or reset all worker's business ID values to the ID of 'b'.
DESCRIPTION:
this is similar to z_migrate_workers(), but does not require the prior business object. Calling this subroutine will simply set everybody in 'workers' to the given business. If 'do_db' is TRUE (the default), the database record corresponding to each worker object will also be updated to reflect the ID of the given business.
 

z_poolsearch_findworker_byperson()
SIGNATURE: const worker_o &wz_poolsearch_findworker_byperson (const person_o &p, vlist_o &workers, count_t &idx, int *pi)
SYNOPSIS: finds the worker corresponding to a given person in a set of workers.
PARAMETERS

  • p: a person object (with a valid ID)
  • workers: a list of workers, one of which is expected to have its person ID be the same as the ID of 'p'
  • idx: [output] the index, (aka position) number of the worker in the list of workers, if found. If no matching worker object is found, the value of this variable is undefined.
  • pi: error indicator variable. The values this variable can have: 0: found, success
DESCRIPTION:
this does a simple linear search, examining each element of 'workers'. Both parameters 'p' and 'workers' should be correctly configured, that is, their IDs ready to be checked.
RETURNS:
[worker_o reference]: a reference to a found worker object
[worker_o::bad_reference()]: no matching object found
 

z_poolsearch_findperson_byworker()
SIGNATURE: const person_o &z_poolsearch_findperson_byworker (const worker_o &w, vlist_o &people, count_t &idx, int *pi)
SYNOPSIS: finds the person corresponding to a given worker in a set of people.
PARAMETERS

  • w: a worker object. This object should have the person's ID pre-loaded into it.
  • workers: a list of workers, one of which is expected to have its person ID be the same as the ID of 'p'
  • idx: [output] the index, (aka position) number of the person in the list of people (in input variable 'oeople'), if a matching object is found. If no matching person object is found, the value of this variable is undefined.
  • pi: error indicator variable. The values this variable can have: 0: found, success
DESCRIPTION:
this does a simple linear search, examining each element of 'people'. Both parameters 'w' and 'people' should be correctly configured, that is, their IDs ready to be checked. If not, that is, if 'w' is a fresh new object with an unassigned ID, or has not had its ID set to a person element that belongs to 'people', the search will fail.
RETURNS:
[person_o reference]: person object was found
[person_o::bad_reference()]: no matching object found
 

z_poolsearch_findworker_byemail()
SIGNATURE: const worker_o &z_poolsearch_findworker_byemail (const email_address_o &x, vlist_o &workers, count_t &idx, int *pi)
SYNOPSIS:
finds the worker, given a set of workers, that owns an e-mail address object that matches the ID of the input parameter 'x'.
PARAMETERS

  • x: an e-mail address object (with a valid ID)
  • workers: a list of workers, one of which is expected to have an e-mail that matches the ID put into 'x'.
  • idx: [output] the index, (aka position) number of the worker in the list of workers, if found. If no matching worker object is found, the value of this variable is undefined.
  • pi: error indicator variable. The values this variable can have: 0: found, success
DESCRIPTION:
this does a simple linear search, examining each element of 'workers'. Both parameters 'x' and 'workers' should be correctly configured, that is, their IDs ready to be checked.
RETURNS:
[worker_o reference]: a reference to a found worker object
[worker_o::bad_reference()]: no matching object found
 

z_poolsearch_findworker_byphone()
SIGNATURE: const worker_o &z_poolsearch_findworker_byphone (const phone_number_o &, vlist_o &workers, count_t &idx, int *pi)
SYNOPSIS:
finds the worker, given a set of workers, that owns an telephone number [object] that matches the ID of the input parameter 'x'.
PARAMETERS

  • x: a phone number object (with a valid ID)
  • workers: a list of workers, one of which is expected to have a telephone whose ID is the same as the ID of 'x'
  • idx: [output] the index, (aka position) number of the worker in the list of workers, if found. If no matching worker object is found, the value of this variable is undefined.
  • pi: error indicator variable. The values this variable can have: 0: found, success
DESCRIPTION:
this does a simple linear search, examining each element of 'workers'. Both parameters 'x' and 'workers' should be correctly configured, that is, their IDs ready to be checked.
RETURNS:
[worker_o reference]: a reference to a found worker object
[worker_o::bad_reference()]: no matching object found
 

usage.
To add properties to a local variable of type worker_o, use put_value():

    worker_o w;
    w.set_value ("title", "Director of All");
    w.set_value ("mail_stop", "49-F");
    w.set_value ("department", "Motivation Analysis");
    w.set_value ("note", "a real prick");
or, provide data from a character string:
static char *folk = "who:	Henry Kissinger\n\
	title: National Security Advisor\n\
	dept: State Department\n\
	arpa: info@henryakissinger.com\n\
	loc: Washington, DC\n\
	what: war criminal\n\
Jane Doe\n\
	phone: (202) 666-6936\n\
	found: 06/06/2013\n\
	loc: next to Jenny\n\
	note: gone shopping\n";

int ie; vlist_o<business_o> businesses; vlist_o<worker_o> workers; alist_o people; business_o biz; string_o sall, serr; z_extract_biz_whoblock(folk, sall, &ie); z_strblock_to_workers (sall, biz, workers, people, &ie, serr);

In the example above you can see the complexity of including lists of businesses, workers, and people. This is necessary, since a worker object is essentially an associative array between a person and a business. This means is that you need to set up a business object and a person object, in addition to supplying the worker object. The worker object will recieve a reference (internally, the IDs of the other objects) to the objects that it binds to.

To add a single worker into the database is a bit tricky. You need to also have a business and person object handy. Follow these steps:

// [0] include requisite header files:
#include "z_worker.h"
#include "z_business.h"
#include "z_person.h"

// [1] allocate variables: int ie0, ie1; business_o b; worker_o w; person_o p = "Theodore Roosevelt"; // assign a name immediately person_o boss;

// [2] set up "pools": alist_o<person_o> people; alist_o<worker_o> workers; alist_o<business_o> businesses; worker_o::set_master_business_pool (&businesses); worker_o::set_master_population_pool (&people);

// [3] set up the variables: w.set_population_pool (&people); w.set_person (p, &ie0); w.set_business (b, &ie1); businesses.add(b);

// [4] configure the worker: p.set_value ("sex", "M", &ie1); // note: a "person" property w.set_value ("title", "Commander in Chief", &ie1); w.set_bossname("Thomas Platt");

// [5] merge the worker into the local population: z_merge_worker_into_population (workers, people, w, p, boss, &ie1);

// [6] add the worker to the database: ie0 = w.store_add(&ie1);

This is the minimal amount of code needed. Of key importance is the set up of "pools", used to aggregate the requisite objects (workers, people, businesses) into a set.

Retrieving a worker, as you proably now may have guessed, a more complex affair. You cannot directly do a "store-fetch where worker's name is so-and-so", since there is no mention of names in the worker table database records. Also, you cannot just retrieve a single worker object. A worker exists in the context of a person and a business; you need to retrieve those objects too. You can retrieve a business with its entire collective of workers with zdb_fetch_workers(); or retrieve a business given a worker with zdb_fetch_business_by_worker(); or use zdb_fetch_worker() to specify search criteria by person and business, and retrieve all 3 objects in one shot. However, this last function has been taken out of the Z Directory for overhaul and repairs, so as of this writing [2013] it is unavailable.

note.
terminology. The rather Marxian term "worker" is used instead of "employee", since an employee is a type of worker. In the context of the geo - people zone of the Z Directory, the intent here is to include any person associated with and doing work for a business (or organization), including employees, contractors, consultants, executives, or directors. The lexicon of workers and businesses is far less precise than, say Newtonian mechanics. A business can on the minimal end be simply a man on the street offering his labor to cut grass or chop trees for a day, and on the high end, it could be a huge multinational corporation. For the purposes here we need an entity to bind a person (person_o) to a business or organization (business_o), indicating that there is a relationship between 2 such objects with a specific start and end time [date].

Technically a director or a contractor would not be classified as an employee. The relationship between the two classes is associative: a business object does not own a worker object, just as a business does not own a worker. Thus, a worker that works for a business, if not a slave, has [possibly multiple] start and end dates. Also, a worker can work for more than one business, possibly at the same time.

warnings.
It is easy to mistake worker_o::set_value() with worker_o::add_value():

void incorrect_usage()
{
    // --THE FOLLOWING LINES ARE INCORRECT!!!--
    worker_o wor;
    wor.set_value ("phone-number", "(202) 555-1414");   // WRONG!
    wor.add_value ("department", "Sales");              // WRONG AGAIN!
}
The data that belongs to one cannot be applied to the other. Remember, repeatable items are added, properties are set.

Another common mistake is to think that deleting a worker record (from a database, that is) deletes the associated record. This is not so. A person can have many worker records, one for each job worked. In object modeling terms, a worker is associated with a person - it does not "own" the person. So, to fully expunge a worker from a database, you must delete the worker, then the person:

int ie0, ie1;
business_o biz;
worker_o wor;
person_o hub = "Daniel Boone";
hub.set_value ("birth_date", "11/02/1734");
hub.set_value ("title",      "Injun fighter");
wor.set_person   (hub, &ie0);
wor.set_business (biz, &ie1);
hub.store_add (&ie1);           // Dan added into the database
wor.store_add (&ie1);           // Dan Boone's job is now in the DB
wor.store_remove();             // this won't delete Boone the person
hub.store_remove();             // ..but this will

limitations.
The problem of trying to accomodate local (in-core) IDs and "external" IDs in this class creates some complexity at the application level. Internally, when calling set_person(), set_boss(), or set_business(), in addition to the key value, there is a flag stored ('person_islocal', 'biz_islocal', 'boss_islocal') that indicates if the local ID is to be used, as opposed to the external ID. The ID value put into the "background panel" databag of the worker_o class can be either local or remote value, depending on whethere or not there is a remote value (if the value is 1 or more, it exists).

bugs.
'time_unit' applies for starting and ending pay rate. This may be insufficient for those rare (?) cases where people have a radical conversion in how they get paid by their employer, but the real world will have to work around this model, and convert/estimate a value, where appropriate. for instance, a person may start as a hired hand paid by the hour, and end up a salesman getting paid by commission.

history.

??? 04/25/1997: changed char(1) -> char(2) for 'self_employed'
??? 03/24/1998: converted this class to a data bag implementation
Sun 03/08/1998: {12:05pm} created z_merge_worker_into_population()
Wed 03/11/1998: complete re-write, z_merge_worker_into_population()
Wed 04/15/1998: z_strblock_to_workers(); text block now all one block
Wed 10/28/1998: file started for "worker" subroutines
Sat 10/24/1998: zdb_fetch_workers(), added: "worker_o::operator = (w)"
??? 11/07/1998: added "educ" keyword
??? 08/29/2001: worker_o::operator = (rec_dbag_o &), slight change
Fri 09/13/2002: unused columns deleted: phone_#, description, position
Sat 09/14/2002: deleted fields "t_end" & "source" [--GeG]
Fri 10/18/2002: adding "#-parse-errors-allowed" control [--GeG]
Thu 06/06/2013: process_who_items(): patched z_bizkw_text ("note") case
Mon 06/10/2013: started on zdb_fetchworker_byname()