NAME
Parse::Taxonomy::MaterializedPath - Validate a file for use as a path-based taxonomy
SYNOPSIS
use Parse::Taxonomy::MaterializedPath;
# 'file' interface: reads a CSV file for you
$source = "./t/data/alpha.csv";
$self = Parse::Taxonomy::MaterializedPath->new( {
file => $source,
} );
# 'components' interface: as if you've already read a
# CSV file and now have Perl array references to header and data rows
$self = Parse::Taxonomy::MaterializedPath->new( {
components => {
fields => $fields,
data_records => $data_records,
}
} );
METHODS
new()
Purpose
Parse::Taxonomy::MaterializedPath constructor.
Arguments
Single hash reference. There are two possible interfaces:
file
andcomponents
.- 1
file
interface -
$source = "./t/data/alpha.csv"; $self = Parse::Taxonomy::MaterializedPath->new( { file => $source, path_col_idx => 0, path_col_sep => '|', %TextCSVoptions, } );
Elements in the hash reference are keyed on:
file
Absolute or relative path to the incoming taxonomy file. Required for this interface.
path_col_idx
If the column to be used as the "path" column in the incoming taxonomy file is not the first column, this option must be set to the integer representing the "path" column's index position (count starts at 0). Optional; defaults to
0
.path_col_sep
If the string used to distinguish components of the path in the path column in the incoming taxonomy file is not a pipe (
|
), this option must be set. Optional; defaults to|
.Text::CSV_XS options
Any other options which could normally be passed to
Text::CSV_XS->new()
will be passed through to that module's constructor. On the recommendation of the Text::CSV documentation,binary
is always set to a true value.
- 2
components
interface -
$self = Parse::Taxonomy::MaterializedPath->new( { components => { fields => $fields, data_records => $data_records, } } );
Elements in this hash are keyed on:
components
This element is required for the
components
interface. The value of this element is a hash reference with two keys,fields
anddata_records
.fields
is a reference to an array holding the field or column names for the data set.data_records
is a reference to an array of array references, each of the latter arrayrefs holding one record or row from the data set.path_col_idx
Same as in
file
interface above.path_col_sep
Same as in
file
interface above.
- 1
Return Value
Parse::Taxonomy::MaterializedPath object.
Comment
new()
will throw an exception under any of the following conditions:Argument to
new()
is not a reference.Argument to
new()
is not a hash reference.In the
file
interface, unable to locate the file which is the value of thefile
element.Argument to
path_col_idx
element is not an integer.Argument to
path_col_idx
is greater than the index number of the last element in the header row of the incoming taxonomy file, i.e., thepath_col_idx
is wrong.The same field is found more than once in the header row of the incoming taxonomy file.
Unable to open or close the incoming taxonomy file for reading.
In the column designated as the "path" column, the same value is observed more than once.
id
,parent_id
,name
,lft
andrgh
are reserved terms. One or more columns is named with a reserved term.A non-parent node's parent node cannot be located in the incoming taxonomy file.
A data row has a number of fields different from the number of fields in the header row.
fields()
Purpose
Identify the names of the columns in the taxonomy.
Arguments
my $fields = $self->fields();
No arguments; the information is already inside the object.
Return Value
Reference to an array holding a list of the columns as they appear in the header row of the incoming taxonomy file.
Comment
Read-only.
path_col_idx()
Purpose
Identify the index position (count starts at 0) of the column in the incoming taxonomy file which serves as the path column.
Arguments
my $path_col_idx = $self->path_col_idx;
No arguments; the information is already inside the object.
Return Value
Integer in the range from 0 to 1 less than the number of columns in the header row.
Comment
Read-only.
path_col()
Purpose
Identify the name of the column in the incoming taxonomy which serves as the path column.
Arguments
my $path_col = $self->path_col;
No arguments; the information is already inside the object.
Return Value
String.
Comment
Read-only.
path_col_sep()
Purpose
Identify the string used to separate path components once the taxonomy has been created. This is just a "getter" and is logically distinct from the option to
new()
which is, in effect, a "setter."Arguments
my $path_col_sep = $self->path_col_sep;
No arguments; the information is already inside the object.
Return Value
String.
Comment
Read-only.
data_records()
Purpose
Once the taxonomy has been validated, get a list of its data rows as a Perl data structure.
Arguments
$data_records = $self->data_records;
None.
Return Value
Reference to array of array references. The array will hold the data records found in the incoming taxonomy file in their order in that file.
Comment
Does not contain any information about the fields in the taxonomy, so you should probably either (a) use in conjunction with
fields()
method above; or (b) usefields_and_data_records()
.
fields_and_data_records()
Purpose
Once the taxonomy has been validated, get a list of its header and data rows as a Perl data structure.
Arguments
$data_records = $self->fields_and_data_records;
None.
Return Value
Reference to array of array references. The first element in the array will hold the header row (same as output of
fields()
). The remaining elements will hold the data records found in the incoming taxonomy file in their order in that file.
data_records_path_components()
Purpose
Once the taxonomy has been validated, get a list of its data rows as a Perl data structure. In each element of this list, the path is now represented as an array reference rather than a string.
Arguments
$data_records_path_components = $self->data_records_path_components;
None.
Return Value
Reference to array of array references. The array will hold the data records found in the incoming taxonomy file in their order in that file.
Comment
Does not contain any information about the fields in the taxonomy, so you may wish to use this method either (a) use in conjunction with
fields()
method above; or (b) usefields_and_data_records_path_components()
.
fields_and_data_records_path_components()
Purpose
Once the taxonomy has been validated, get a list of its data rows as a Perl data structure. The first element in this list is an array reference holding the header row. In each data element of this list, the path is now represented as an array reference rather than a string.
Arguments
$fields_and_data_records_path_components = $self->fields_and_data_records_path_components;
None.
Return Value
Reference to array of array references. The array will hold the data records found in the incoming taxonomy file in their order in that file.
get_field_position()
Purpose
Identify the index position of a given field within the header row.
Arguments
$index = $self->get_field_position('income');
Takes a single string holding the name of one of the fields (column names).
Return Value
Integer representing the index position (counting from
0
) of the field provided as argument. Throws exception if the argument is not actually a field.
descendant_counts()
Purpose
Display the number of descendant (multi-generational) nodes each node in the taxonomy has.
Arguments
$descendant_counts = $self->descendant_counts(); $descendant_counts = $self->descendant_counts( { generations => 1 } );
None required; one optional hash reference. Currently, the only element honored in that hashref is
generations
, whose value must be a non-negative integer. If, instead of getting the count of all descendants of a node, you only want the count of its first generation, i.e., its immediate children, you provide a value of1
. Want the count of only the first and second generations? Provide a value of2
-- and so on.Return Value
Reference to hash in which each element is keyed on the value of the path column in the incoming taxonomy file.
get_descendant_count()
Purpose
Get the total number of descendant nodes for one specific node in a validated taxonomy.
Arguments
$descendant_count = $self->get_descendant_count('|Path|To|Node'); $descendant_counts = $self->get_descendant_count('|Path|To|Node', { generations => 1 } );
One required: string containing node's path as spelled in the taxonomy.
One optional hash reference. Currently, the only element honored in that hashref is
generations
, whose value must be a non-negative integer. If, instead of getting the count of all descendants of a node, you only want the count of its first generation, i.e., its immediate children, you provide a value of1
. Want the count of only first and second generations? Provide a value of2
-- and so on.Return Value
Unsigned integer >= 0. Any node whose child count is
0
is by definition a leaf node.Comment
Will throw an exception if the node does not exist or is misspelled.
If
get_descendant_count()
is called with no second (hashref) argument following an invocation ofdescendant_counts()
, it will return a value from an internal cache created during that earlier method call. Otherwise, it will re-create the cache from scratch. (This, of course, assumes that you have not manipulated the object's internal data subsequent to its creation.)
hashify()
Purpose
Turn a validated taxonomy into a Perl hash keyed on the column designated as the path column.
Arguments
$hashref = $self->hashify();
Takes an optional hashref holding a list of any of the following elements:
remove_leading_path_col_sep
Boolean, defaulting to
0
. By default,hashify()
will spell the key of the hash exactly as the value of the path column is spelled in the taxonomy -- which in turn is the way it was spelled in the incoming file. That is, a path in the taxonomy spelled|Alpha|Beta|Gamma
will be spelled as a key in exactly the same way.However, since in many cases (including the example above) the root node of the taxonomy will be empty, the user may wish to remove the first instance of
path_col_sep
. The user would do so by settingremove_leading_path_col_sep
to a true value.$hashref = $self->hashify( { remove_leading_path_col_sep => 1, } );
In that case they key would now be spelled:
Alpha|Beta|Gamma
.Note further that if the
root_str
switch is set to a true value, any setting toremove_leading_path_col_sep
will be ignored.key_delim
A string which will be used in composing the key of the hashref returned by this method. The user may select this key if she does not want to use the value found in the incoming CSV file (which by default will be the pipe character (
|
) and which may be overridden with thepath_col_sep
argument tonew()
.$hashref = $self->hashify( { key_delim => q{ - }, } );
In the above variant, a path that in the incoming taxonomy file was represented by
|Alpha|Beta|Gamma
will in$hashref
be represented by- Alpha - Beta - Gamma
.root_str
A string which will be used in composing the key of the hashref returned by this method. The user will set this switch if she wishes to have the root note explicitly represented. Using this switch will automatically cause
remove_leading_path_col_sep
to be ignored.Suppose the user wished to have
All Suppliers
be the text for the root node. Suppose further that the user wanted to use the string-
as the delimiter within the key.$hashref = $self->hashify( { root_str => q{All Suppliers}, key_delim => q{ - }, } );
Then incoming path
|Alpha|Beta|Gamma
would be keyed as:All Suppliers - Alpha - Beta - Gamma
Return Value
Hash reference. The number of elements in this hash should be equal to the number of non-header records in the taxonomy.
adjacentify()
Purpose
Transform a taxonomy-by-materialized-path into a taxonomy-by-adjacent-list.
Arguments
$adjacentified = $self->adjacentify(); $adjacentified = $self->adjacentify( { serial => 500 } ); $adjacentified = $self->adjacentify( { floor => 500 } ); # same as serial
Optional single hash reference.
For that hashref,
adjacentify()
supports the keyserial
, which defaults to0
.serial
must be a non-negative integer and sets the "floor" above which new unique IDs will be assigned to theid
column. Hence, ifserial
is set to500
, the value assigned to theid
column of the first record to be processed will be501
.Starting with version .19,
floor
will serve as an alternative way of providing the same information toadjacentify()
. If, however, by mistake you provide bothserial
andfloor
elements in the hash,serial
will take precedence.Return Value
Reference to an array of hash references. Each element represents one node in the taxonomy. Each element will have key-value pairs for
id
,parent_id
andname
which will hold the adjacentification of the materialized path in the original taxonomy-by-materialized-path. Each element will, as well, have KVPs for the non-materialized-path fields in the records in the original taxonomy-by-materialized-path.Comment
See documentation for
write_adjacentified_to_csv()
for example.Note that the order in which
adjacentify()
will assignid
andparent_id
values to records in the taxonomy-by-adjacent-list will almost certainly not match the order in which elements appear in a CSV file or in the data structure returned by a method such asdata_records()
.
write_adjacentified_to_csv()
Purpose
Create a CSV-formatted file holding the data returned by
adjacentify()
.Arguments
$csv_file = $self->write_adjacentified_to_csv( { adjacentified => $adjacentified, # output of adjacentify() csvfile => './t/data/taxonomy_out3.csv', } );
Single hash reference. That hash is keyed on:
adjacentified
Required: Its value must be the arrayref of hash references returned by the
adjacentify()
method.csvfile
Optional. Path to location where a CSV-formatted text file holding the taxonomy-by-adjacent-list will be written. Defaults to a file called taxonomy_out.csv in the current working directory.
Text::CSV_XS options
You can also pass through any key-value pairs normally accepted by Text::CSV_XS.
Return Value
Returns path to CSV-formatted text file just created.
Example
Suppose we have a CSV-formatted file holding the following taxonomy-by-materialized-path:
"path","is_actionable" "|Alpha","0" "|Beta","0" "|Alpha|Epsilon","0" "|Alpha|Epsilon|Kappa","1" "|Alpha|Zeta","0" "|Alpha|Zeta|Lambda","1" "|Alpha|Zeta|Mu","0" "|Beta|Eta","1" "|Beta|Theta","1"
After running this file through
new()
,adjacentify()
andwrite_adjacentified_to_csv()
we will have a new CSV-formatted file holding this taxonomy-by-adjacent-list:id,parent_id,name,is_actionable 1,,Alpha,0 2,,Beta,0 3,1,Epsilon,0 4,1,Zeta,0 5,2,Eta,1 6,2,Theta,1 7,3,Kappa,1 8,4,Lambda,1 9,4,Mu,0
Note that the
path
column has been replaced by theid
,parent_id
andname
columns.