# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2019 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
package MC_cli_display_utils; 
# sccsid = "@(#)57   1.34   src/rsct/rmc/cli/pm/MC_cli_display_utils.pm.perl, rmccli, rsct_rady, rady2035a 11/12/15 16:30:04"
######################################################################
#                                                                    #
# Package: MC_cli_display_utils.pm                                   #
#                                                                    #
# Description:                                                       #
#   This package contains common display subroutines for the RMC     #
#   Perl Command Line Interface.                                     #
#                                                                    #
# Subroutines exported:                                              #
#   convert_properties - Converts the properties integer values      #
#     and converts it to an array of CT_CHAR_PTR / a printable       #
#     string of properties. On input the integer properties should   #
#     be a valid oring of the enums within mc_rsrc_class_props_t,    #
#     or mc_pattr_propts_t, or mc_dattr_props_t                      #
#       on input ptype = 'pattr';                                    #
#       on input properties = 0x21                                   #
#       on output CT_CHAR_PTR_ARRAY, {read_only,required_for_define} #
#                                                                    #
#   convert_variable_type - Takes an rmc_variable_type_t, an int,    #
#     and converts it to a CT_CHAR_PTR / a printable string. One of: #
#     counter, quantity, state, quantum, or undefined.               #
#                                                                    #
#   convert_variety_list - Takes a pointer to a mc_variety_t         #
#     and returns the variety list as an array of SDs:               #
#     {[first_variety,last_variety],[first_variety,last_variety],    #
#      ...}   for variety_count.                                     #
#                                                                    # 
#   convert_valid_values - Converts a list of attribute valid values # 
#     into a format suitable for printing. Takes a pointer to a      # 
#     mc_qdef_valid_vals_rsp_t structure and returns a reference to  #
#     an array of valid values or valid ranges. Return type is       # 
#     either CT_CHAR_PTR_ARRAY, CT_SD_PTR_ARRAY or CT_NONE and an    # 
#     empty array if no valid values are specified for the           # 
#     attribute or if the attribute is either type CT_SD_PTR or      # 
#     CT_SD_PTR_ARRAY or an unrecognized data type. This function    # 
#     does not handle structured data type attribute valid values.   # 
#                                                                    # 
#   convert_sd_valid_values - Converts a list of an attribute's      # 
#     SD elements' valid values into a format suitable for printing. # 
#     Takes a pointer to a mc_qdef_valid_vals_rsp_t structure and    # 
#     returns a reference to an array of valid values or valid       #
#     ranges. Return type is either CT_CHAR_PTR_ARRAY,               # 
#     CT_SD_PTR_ARRAY or CT_NONE and an empty array if no valid      # 
#     values are specified for the attribute or its SD elements or   # 
#     if the elements' data types are not recognized. This function  # 
#     was specifically designed to work with the elements of         # 
#     attributes whose data type is either CT_SD_PTR or              # 
#     CT_SD_PTR_ARRAY.                                               # 
#                                                                    # 
#   convert_valid_values_label - Converts a list of valid values     # 
#     labels (descriptions) into a character array. Returns          # 
#     CT_CHAR_PTR_ARRAY as the data type and a reference to a list   # 
#     of descriptions. This function does not handle structured data # 
#     type attributes.                                               #
#                                                                    #
#   convert_sd_valid_values_label - Converts a list of valid values  # 
#     labels (descriptions) into a character array. Returns          # 
#     CT_CHAR_PTR_ARRAY as the data type and a reference to a list   # 
#     of descriptions. This function only handles attributes of type # 
#     CT_SD_PTR or CT_SD_PTR_ARRAY.                                  # 
#                                                                    # 
#   display_resource_class_names - Use this after a call to          #
#     qdef_resource_class to display the list of all defined         #
#     resource class names on the system.                            #
#                                                                    #
#   display_resource_data - Takes one rHoPattr(Dattr) and prints     #
#     it to the CLI output using the CT display utility.             #
#                                                                    #
#   display_joined_resource_data - Takes both a rHoPattr and         #
#     rHoDattr and prints it to the CLI output using the CT print    #
#     utilities.                                                     #
#       - rHoPAttr - Ref to Hash of Persistent attr.                 #
#       - rHoDAttr - Ref to Hash of Dynamic attr.                    #
#     The two tables are joined using the attr_name:                 #
#       MC_FKEY*PATTR_TO_DATTR_KEY*MC_FKEY                           #
#       and comparing the resource handle values                     #
#       using CT::CU::rsrcs_are_same extension.                      #
#                                                                    #
# (*) Format for the hash is as follows:                             #
#  @HoAttr = {                                                       #
#    <at_name> => [                                                  #
#       {at_name  => $string,         at_id => $int,                 #
#        at_dtype => $ct_data_type_t, at_value => $scalar_reference},#
#       {at_name  => $string,         at_id => $int,                 #
#        at_dtype => $ct_data_type_t, at_value => $scalar_reference},#
#       ...                                                          #
#    ],                                                              #
#  }                                                                 #
#   where at refers to 'attribute' in all names above                #
#                                                                    #
#                                                                    #
# Other subroutines included in this package:                        #
#     set_print_array - This is the primary subroutine for pulling   #
#                     data out of the hashes and putting them in a   #
#                     2-D array format suitable for the CT print     #
#                     facility.                                      #
#                                                                    #
#   getIMsg - returns the text of a message. Used for NLS.           #
#     Requires the program name and message mnemonic as inputs.      #
#                                                                    #
# Examples for exported subroutines:                                 #
#                                                                    #
# To display two reference hashes using long format:                 #
# (NOTE: delimiter can be passed in as "" because it is ignored      #
#  for all but the delimiter output case.)                           #
#                                                                    #
# display_joined_resource_data("long", $no_header,                   #
#          \@attributes_to_print, $row_header,   \%HoPAttr,          #
#          \%HoDAttr, "", \@title);                                  #
#                                                                    #
# To display one reference hash using delim format:                  #
#                                                                    #
# display_resource_data("delim", $no_header, \@attributes_to_print,  #
#          $row_header, \%HoPAttr, $delimiter, \@title);             #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /opt/rsct/msgmaps/mccli.mccli.map - message mapping         #
#                                                                    #
# Outputs:                                                           #
#   stdout - common informational messages that get displayed.       #
#          - all display output.                                     #
#   stderr - common error messages that get displayed.               #
#                                                                    #
# External References:                                               #
#   Commands: ctdspmsg                                               #
#   Extensions:  MC.pm, CT.pm                                        #
#   Perl Modules:  CT_cli_display_utils.pm                           #
#                                                                    #
# Tab Settings:                                                      #
#   4 and tabs should be expanded to spaces before saving this file. #
#   in vi:  (:set ts=4  and   :%!expand -4)                          #
#                                                                    #
# Change Activity:                                                   #
#   991230 HGJ 60032: Initial design and write.                      #
#   010806 YSK 75111: Added:                                         #
#                     convert_valid_values,                          # 
#                     convert_sd_valid_values,                       # 
#                     convert_valid_values_label,                    # 
#                     convert_sd_valid_values_label.                 # 
#   020925 JAC 87393: Change CT_cli_display_utils to .._displayext.. #
#   020826 JAC 86229: Make changes to eliminate perl extensions.     #
#   021020 JAC 88082: Add functions to use rmc api commands.         #
#   030106 JAC 88088: Remove perl extension references.              #
#   030115 JAC 90884: Remove perl extension references.              #
#   040604 JAC 110003: Fix to set_print_array_api for how split works#
#   080122 JAC 145056: add getIMsg.                                  #
#   080724 JAC 151272: allow to set starting row number on output.   #
######################################################################

use Exporter ();
@ISA = qw(Exporter);
@EXPORT_OK = qw(
    display_resource_data_api
    display_resource_data_api2
    display_resource_data_api3
    convert_properties
    convert_variable_type
    convert_variety_list
    convert_valid_values
    convert_sd_valid_values
    convert_valid_values_label
    convert_sd_valid_values_label
    getIMsg
);

use lib "/opt/rsct/pm";
use locale;

use CT_cli_display_utils qw(
    set_display
);
####use CT_cli_data_type_utils qw(
####    data_type_is_numeric
####    array_data_type_to_simple
####);

use MC_cli_rc qw(:return_codes);
use MC_cli_utils qw(build_HoAttr);


#--------------------------------------------------------------------#
# Note: NLS decision for RMC CLI.                                    #
#   the ..._property_to_string tables are not translated.            #
#   This was an NLS decision to keep the property values closely     #
#   matching the enum values defined in ct_mc.h. RMC CLI no          #
#   translation of attribute names, element names, program names     #
#   or enums. Prefixes and suffixes may be dropped and lower case    #
#   used for readability.                                            #
#   If the ...property_to_string tables must be translated due to    #
#   some future decision - only 1 message should be used for each    #
#   of the 3 property tables for performance reasons.                #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# mc_rsrc_class_props_t enums defined in MC::MC.pm                   #
# used by convert_properties.                                        #
#--------------------------------------------------------------------#
%class_property_to_string = (
    eval(MC_RSRC_CLASS_RESERVED)            => "reserved",
    eval(MC_RSRC_CLASS_HAS_RSRC_INSTS)      => "has_rsrc_insts",
    eval(MC_RSRC_CLASS_HAS_CTRL_INTERFACE)  => "has_ctrl_interface",
    eval(MC_RSRC_CLASS_CAN_DEFINE_UNDEFINE) => "can_define_undefine",
    eval(MC_RSRC_CLASS_INVOKE_PHASE0)       => "invoke_phase0",
    eval(MC_RSRC_CLASS_INVOKE_PHASE1)       => "invoke_phase1",
    eval(MC_RSRC_CLASS_PERFMON_SUPPORTED)   => "perfmon_supported",
    eval(MC_RSRC_CLASS_HAS_CONSTRAINTS)     => "has_constraints", 
    eval(MC_RSRC_CLASS_RMC_ELECTS_COORD)    => "rmc_elects_coord", 
    eval(MC_RSRC_CLASS_MTYPE_SUBDIVIDED)    => "mtype_subdivided",
    eval(MC_RSRC_CLASS_MTYPE_CENTRALIZED)   => "mtype_centralized",
    eval(MC_RSRC_CLASS_MTYPE_GLOBALIZED)    => "mtype_globalized"
);

#--------------------------------------------------------------------#
# mc_pattr_props_t enums defined in MC::MC.pm                        #
# used by convert_properties.                                        #
#--------------------------------------------------------------------#
%pattr_property_to_string = (
    eval(MC_RSRC_PATTR_READ_ONLY)           => "read_only",
    eval(MC_RSRC_PATTR_REQD_FOR_DEFINE)     => "reqd_for_define", 
    eval(MC_RSRC_PATTR_INVAL_FOR_DEFINE)    => "inval_for_define",
    eval(MC_RSRC_PATTR_OPTION_FOR_DEFINE)   => "option_for_define",
    eval(MC_RSRC_PATTR_SELECTABLE)          => "selectable",
    eval(MC_RSRC_PATTR_PUBLIC)              => "public"
);

#--------------------------------------------------------------------#
# mc_pattr_props_t enums defined in MC::MC.pm                        #
# used by convert_properties.                                        #
#--------------------------------------------------------------------#
%dattr_property_to_string = (
    eval(MC_RSRC_DATTR_PUBLIC)              => "public"
);

#--------------------------------------------------------------------#
# mc_action_props_t enums defined in MC::MC.pm                       #
# used by convert_properties.                                        #
#--------------------------------------------------------------------#
%action_property_to_string = (
    eval(MC_RSRC_ACTION_LONG_RUNNING)       => "long_running",
    eval(MC_RSRC_ACTION_PUBLIC)             => "public"
);


#--------------------------------------------------------------------#
# Begin Exported Subroutines (with @EXPORT_OK, -> on demand).        #
#--------------------------------------------------------------------#



#--------------------------------------------------------------------#
# display_resource_data_api                                          #
#   Write table data to STDOUT in column, long, file, or delimited   #
#   format. Calls either column_display, long_display, or            #
#   delim_display.                                                   #
#                                                                    #
# Parameters:                                                        #
#   $display_type - type of display - column, long or delim          #
#   $no_header    - (boolean) header suppression flag                #
#   $attributes_to_print - list of attributes to be printed out      #
#                    (aka header information.)                       #
#   $row_header  - reference to array of strings to be used as row   #
#                header info (specifically for long format display)  #
#   $data        - rHoPAttr of rHoDAttr, as described in file prolog #
#   $delim        - (optional) delimiter to be used with delim       #
#                   display type.                                    #
#   $title        - (optional) array of titles to be displayed at the#
#                 top of the Persistent and dynamic data tables.     #
#                 Persistent title is $title->[0], Dynamic title is  #
#                 $title->[1].                                       #
#                                                                    #
# Returns:                                                           #
#   $local_rc     - 0 if command completes successfully              #
#                 - 1 if invalid display type                        #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5   input  To print trace information if requested.  #
#--------------------------------------------------------------------#
sub display_resource_data_api
{
my ($display_type,
    $no_header,
    $attributes_to_print,
    $row_header,
    $data,
    $delim,
    $title) = @_;

my $col = 0;
my $row = 0;

($row, $col, $printable_data) =
    set_print_array_api($attributes_to_print, $row_header, $title, $data);

# Call the routine that will shunt the data to the appropriate
# display routine, based on the display type.
$local_rc = set_display( $display_type, $no_header, $row,
        $col, $printable_data, $delim );

$main::Trace5 &&
    print STDERR "Leaving MC_cli_display_utils::display_resource_data_api($local_rc)\n";

return $local_rc;
}   # end display_resource_data_api


#--------------------------------------------------------------------#
# display_resource_data_api2                                         #
#   Write table data to STDOUT in column, long, file, or delimited   #
#   format. Calls either column_display, long_display, or            #
#   delim_display.                                                   #
#                                                                    #
# Parameters:                                                        #
#   $display_type - type of display - column, long or delim          #
#   $no_header    - (boolean) header suppression flag                #
#   $attributes_to_print - list of attributes to be printed out      #
#                    (aka header information.)                       #
#   $row_header  - reference to array of strings to be used as row   #
#                header info (specifically for long format display)  #
#   $data        - rHoPAttr of rHoDAttr, as described in file prolog #
#   $delim        - (optional) delimiter to be used with delim       #
#                   display type.                                    #
#   $title        - (optional) array of titles to be displayed at the#
#                 top of the Persistent and dynamic data tables.     #
#                 Persistent title is $title->[0], Dynamic title is  #
#                 $title->[1].                                       #
#                                                                    #
# Returns:                                                           #
#   $local_rc     - 0 if command completes successfully              #
#                 - 1 if invalid display type                        #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5   input  To print trace information if requested.  #
#--------------------------------------------------------------------#
sub display_resource_data_api2
{
my ($display_type,
    $no_header,
    $attributes_to_print,
    $row_header,
    $data,
    $delim,
    $title) = @_;

my $col = 0;
my $row = 0;

($row, $col, $printable_data) =
    set_print_array_api2($attributes_to_print, $row_header, $title, $data);

# Call the routine that will shunt the data to the appropriate
# display routine, based on the display type.
$local_rc = set_display( $display_type, $no_header, $row,
        $col, $printable_data, $delim );

$main::Trace5 &&
    print STDERR "Leaving MC_cli_display_utils::display_resource_data_api2($local_rc)\n";

return $local_rc;
}   # end display_resource_data_api2


#--------------------------------------------------------------------#
# display_resource_data_api3                                         #
#   Write table data to STDOUT in column, long, file, or delimited   #
#   format. Calls either column_display, long_display, or            #
#   delim_display. Has a starting count for the row numbers.         #
#                                                                    #
# Parameters:                                                        #
#   $display_type - type of display - column, long or delim          #
#   $no_header    - (boolean) header suppression flag                #
#   $attributes_to_print - list of attributes to be printed out      #
#                    (aka header information.)                       #
#   $row_header  - reference to array of strings to be used as row   #
#                header info (specifically for long format display)  #
#   $data        - rHoPAttr of rHoDAttr, as described in file prolog #
#   $delim        - (optional) delimiter to be used with delim       #
#                   display type.                                    #
#   $title        - (optional) array of titles to be displayed at the#
#                 top of the Persistent and dynamic data tables.     #
#                 Persistent title is $title->[0], Dynamic title is  #
#                 $title->[1].                                       #
#   $start_num    - the number to start with in numbering the rows   #
#                   of output.                                       #
#                                                                    #
# Returns:                                                           #
#   $local_rc     - 0 if command completes successfully              #
#                 - 1 if invalid display type                        #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5   input  To print trace information if requested.  #
#--------------------------------------------------------------------#
sub display_resource_data_api3
{
my ($display_type,
    $no_header,
    $attributes_to_print,
    $row_header,
    $data,
    $delim,
    $title,
    $start_num) = @_;

my $col = 0;
my $row = 0;

($row, $col, $printable_data) =
    set_print_array_api3($attributes_to_print, $row_header, $title, $data, $start_num);

# Call the routine that will shunt the data to the appropriate
# display routine, based on the display type.
$local_rc = set_display( $display_type, $no_header, $row,
        $col, $printable_data, $delim );

$main::Trace5 &&
    print STDERR "Leaving MC_cli_display_utils::display_resource_data_api3($local_rc)\n";

return $local_rc;
}   # end display_resource_data_api3


#--------------------------------------------------------------------#
# convert_properties - converts the class, persistent attribute,     #
#   or dynamic attribute resource property from its numeric value    #
#   to an array of strings.                                          #
#                                                                    #
# Parameters:                                                        #
#   $properties   in   Property numeric value a number that should   #
#                      be from an oring of values within:            #
#                      CT::MC::mc_rsrc_class_props_t                 #
#                      CT::MC::mc_pattr_props_t                      #
#                      CT::MC::mc_dattr_props_t                      #
#                      CT::MC::mc_action_props_t                     #
#   $type         in   Indication if the property is a               #
#                      class, pattr, dattr, action property.         #
#                                                                    #
# Returns:                                                           #
#   $data_type    - CT_CHAR_PTR_ARRAY.                               #
#   $value        - Array of string properties.                      #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5 - to print trace information if requested          #
#--------------------------------------------------------------------#
sub convert_properties
{
my ($properties, $type) = @_;

$main::Trace5 && 
    print STDERR "Entered MC_cli_display_utils::convert_properties($properties, $type)\n";

my @def_properties = ();
if ($type eq "pattr") {
    @def_properties = keys %pattr_property_to_string;
    $r_property_to_string = \%pattr_property_to_string;
}
elsif ($type eq "dattr") {
    @def_properties = keys %dattr_property_to_string;
    $r_property_to_string = \%dattr_property_to_string;
}
elsif ($type eq "class") {
    @def_properties = keys %class_property_to_string;
    $r_property_to_string = \%class_property_to_string;
} 
elsif ($type eq "action") {
    @def_properties = keys %action_property_to_string;
    $r_property_to_string = \%action_property_to_string;
}

my @property_strings = ();          # property in string format
foreach $def_property (@def_properties) {
    if ($def_property & $properties) {
        push @property_strings, $$r_property_to_string{$def_property};
    }
} 

$main::Trace5 && 
    print STDERR "Leaving MC_cli_display_utils::convert_properties(CT_CHAR_PTR_T, @property_strings)\n";

return (CT_CHAR_PTR_ARRAY, \@property_strings);
}   # end convert_properties


#--------------------------------------------------------------------#
# convert_variable_type - converts the dynamic attribute variable    #
#   type from its numeric (enum) representation to a printable       #
#   string that represents that enum as defined in                   #
#   rmc_variable_type_t in ct_rmc.h                                  #
#                                                                    #
# Parameters:                                                        #
#   $variable_type in  Variable type numeric value:                  #
#                      0 RMC_COUNTER                                 #
#                      1 RMC_QUANTITY                                #
#                      2 RMC_STATE                                   #
#                      3 RMC_QUANTUM                                 #
#                                                                    #
# Returns:                                                           #
#   $data_type    - Data being returned is CT_CHAR_PTR.              #
#   $string       - The string representation of the variable type.  #
#                   "counter", "quantity", "state", "quantum".       #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5 - to print trace information if requested          #
#--------------------------------------------------------------------#
sub convert_variable_type
{
my ($variable_type) = @_;

$main::Trace5 && 
    print STDERR "Entered MC_cli_display_utils::convert_variable_type($variable_type)\n";

# TODO: At some point if there is more reason to code a Perl to C
# extension for ct_rmc.h, the rmc_variable_type_t enum should be
# coded in the CT::RMC.pm. But simply coding this one enum in its
# own Perl Module is not efficient.
# Note: NLS we are not translating programmic names since enums
# correspond to a value in a header file.
local %variable_type_to_string = (
    0   => "counter",
    1   => "quantity",
    2   => "state",
    3   => "quantum"
);

my $string = $variable_type_to_string{$variable_type};

if (!defined $string) {
    $string = "undefined";
}

$main::Trace5 &&
    print STDERR "Exited MC_cli_display_utils::convert_variable_type($string)\n";
return (CT_CHAR_PTR, $string);
}   # end convert_variable_type


#--------------------------------------------------------------------#
# End Exported Subroutines (with @EXPORT_OK, -> on demand).          #
#--------------------------------------------------------------------#


#--------------------------------------------------------------------#
# set_print_array_api2                                               #
#   Starting with a reference to a hash of the following format:     #
#   @HoAttr = {                                                      #
#     <at_name> => [                                                 #
#       {at_name  => $string,         at_id => $int,                 #
#        at_dtype => $ct_data_type_t, at_value => $scalar_reference},#
#       {at_name  => $string,         at_id => $int,                 #
#        at_dtype => $ct_data_type_t, at_value => $scalar_reference},#
#       ...                                                          #
#     ],                                                             #
#   }                                                                #
#   Convert the data contained in the reference to a 2-D array, of   #
#   the format required to call the set_display routine from the     #
#   CT::CT print facility.                                           #
#                                                                    #
# Parameters:                                                        #
#   $column_headers - array of column header names to appear in the  #
#                  first row of the output array.                    #
#   $row_header  - array of row header names to be used for long     #
#                  format display.                                   #
#   $title        - title for the display                            #
#   $input_hash   - reference to an input hash with the above format #
#                                                                    #
# Returns:                                                           #
#   $row_count    - number of rows in the output array.              #
#   $col_count    - number of rows in the output array.              #
#   $output_array - reference to the newly created array of data.    #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5    input  Print trace information if requested.    #
#--------------------------------------------------------------------#
sub set_print_array_api2
{
# Grab input parameters
my ($column_headers, 
    $row_header,
    $title, 
    $input_hash) = @_;

$main::Trace5 && print STDERR "Entered MC_cli_display_utils::set_print_array_api2($column_headers, $row_header, $title, $input_hash)\n";

# Set up local variables
my $at_name;
my $element;
my @output_array;
my $id;
my $type;
my $value;
my $maxrow = 1;
my $col = 1;
my $row = 1;
my $local_rc = 0;

# Set title in the corner spot
$output_array[0][0] = $title;

# Set up the (column) header row for the array
# foreach (@$column_headers) {
# TODO: hanging on to this code for possible later
# use for displaying SD type.
#    $largest = length($_);
#    if ($spacing_size < $largest) { $spacing_size = $largest; }
# }

# Set up the row header column for the array:


# Set up the other rows in the array
# First column is for the row header information
$maxrow = 1;
$col = 1;
$row = 1;

# only display if something in the input_hash
if (scalar(keys %$input_hash) > 0) {
    foreach $at_name (@$column_headers) {
        $row = 1;
        # $input_hash->{$at_name} should be an array of hashes
        # for this $at_name. Each has contains the
        # at_name, at_value, at_dtype
        if (exists $input_hash->{$at_name}) {
            foreach $element (@{$input_hash->{$at_name}}) {

                if ($element->{at_name} eq $at_name) {
                    $type = $element->{at_dtype};
                    $id = $element->{at_id};
                    $value = $element->{at_value};

                    # Convert the entries to strings as necessary
                    # based on the data type

                    #$output_array[$row][$col] = 
                    #    convert_value($type, $value);
                    $output_array[$row][$col] = $value;

                    $output_array[$row][0] = $row_header." $row:"; 
                    $row++;
                    if ($maxrow < $row) { $maxrow = $row; }
                }

            } # end foreach $element

        } # end if (exits $input_hash->{$at_name})
        else {  
            # If we get here the attribute name was one that was
            # required to be displayed even if RMC never returned
            # a value for it. Attributes listed on the command line
            # are always displayed even if no value returned from RMC.
            #$output_array[$row][$col] = convert_value(CT_NONE, "");
            $output_array[$row][$col] = "";
        } 
        $output_array[0][$col] = $at_name;
        $col++;
    }   # end foreach $at_name  

    # Fill up any undefined entries in the array with CT_NONE
    $col = 1;   
    foreach $at_name (@$column_headers) {
        for ($row = 1; $row < $maxrow; $row++) {
            if (!defined $output_array[$row][$col]) { 
                $output_array[$row][$col] = "";
            }
        }
        $col++;
    }   # end foreach $at_name (@$column_headers)

}   # end scalar(keys %$input_hash) > 0

$main::Trace5 && 
    print STDERR "Leaving MC_cli_display_utils::set_print_array_api2($local_rc, $maxrow - 1, $col, @output_array)\n";

#return ($local_rc, $maxrow - 1, $col, \@output_array);
return ($maxrow - 1, $col, \@output_array);
}   # end set_print_array_api2


#--------------------------------------------------------------------#
# set_print_array_api3                                               #
#   Starting with a reference to a hash of the following format:     #
#   @HoAttr = {                                                      #
#     <at_name> => [                                                 #
#       {at_name  => $string,         at_id => $int,                 #
#        at_dtype => $ct_data_type_t, at_value => $scalar_reference},#
#       {at_name  => $string,         at_id => $int,                 #
#        at_dtype => $ct_data_type_t, at_value => $scalar_reference},#
#       ...                                                          #
#     ],                                                             #
#   }                                                                #
#   Convert the data contained in the reference to a 2-D array, of   #
#   the format required to call the set_display routine from the     #
#   CT::CT print facility.                                           #
#                                                                    #
# Parameters:                                                        #
#   $column_headers - array of column header names to appear in the  #
#                  first row of the output array.                    #
#   $row_header  - array of row header names to be used for long     #
#                  format display.                                   #
#   $title        - title for the display                            #
#   $input_hash   - reference to an input hash with the above format #
#   $start_num    - the number to start with in numbering the rows   #
#                   of output.                                       #
#                                                                    #
# Returns:                                                           #
#   $row_count    - number of rows in the output array.              #
#   $col_count    - number of rows in the output array.              #
#   $output_array - reference to the newly created array of data.    #
#                                                                    #
# Global References:                                                 #
#   $main::Trace5    input  Print trace information if requested.    #
#--------------------------------------------------------------------#
sub set_print_array_api3
{
# Grab input parameters
my ($column_headers,
    $row_header,
    $title,
    $input_hash,
    $start_num) = @_;

$main::Trace5 && print STDERR "Entered MC_cli_display_utils::set_print_array_api3($column_headers,
       $row_header, $title, $input_hash,$start_num)\n";

# Set up local variables
my $at_name;
my $element;
my @output_array;
my $id;
my $type;
my $value;
my $maxrow = 1;
my $col = 1;
my $row = 1;
my $local_rc = 0;
my $row_num_label = $start_num;

# Set title in the corner spot
$output_array[0][0] = $title;

# Set up the (column) header row for the array
# foreach (@$column_headers) {
# TODO: hanging on to this code for possible later
# use for displaying SD type.
#    $largest = length($_);
#    if ($spacing_size < $largest) { $spacing_size = $largest; }
# }

# Set up the row header column for the array:


# Set up the other rows in the array
# First column is for the row header information
$maxrow = 1;
$col = 1;
$row = 1;

# only display if something in the input_hash
if (scalar(keys %$input_hash) > 0) {
    foreach $at_name (@$column_headers) {
        $row = 1;
        $row_num_label = $start_num;
        # $input_hash->{$at_name} should be an array of hashes
        # for this $at_name. Each has contains the
        # at_name, at_value, at_dtype
        if (exists $input_hash->{$at_name}) {
            foreach $element (@{$input_hash->{$at_name}}) {

                if ($element->{at_name} eq $at_name) {
                    $type = $element->{at_dtype};
                    $id = $element->{at_id};
                    $value = $element->{at_value};

                    $output_array[$row][$col] = $value;

                    $output_array[$row][0] = $row_header." $row_num_label:";
                    $row++;
                    $row_num_label++;
                    if ($maxrow < $row) { $maxrow = $row; }
                }

            } # end foreach $element

        } # end if (exits $input_hash->{$at_name})
        else {
            # If we get here the attribute name was one that was
            # required to be displayed even if RMC never returned
            # a value for it. Attributes listed on the command line
            # are always displayed even if no value returned from RMC.
            #$output_array[$row][$col] = convert_value(CT_NONE, "");
            $output_array[$row][$col] = "";
        }

        # Substitute ACT_RSP_ELE_\d+ back to its type - see defect 159922
        if ($at_name =~ /^ACT_RSP_ELE_\d+$/) {
            $output_array[0][$col] = "($type)";
        }
        else
        {
            $output_array[0][$col] = $at_name;
        }
        $col++;
    }   # end foreach $at_name

    # Fill up any undefined entries in the array with CT_NONE
    $col = 1;
    foreach $at_name (@$column_headers) {
        for ($row = 1; $row < $maxrow; $row++) {
            if (!defined $output_array[$row][$col]) {
                $output_array[$row][$col] = "";
            }
        }
        $col++;
    }   # end foreach $at_name (@$column_headers)

}   # end scalar(keys %$input_hash) > 0

$main::Trace5 &&
    print STDERR "Leaving MC_cli_display_utils::set_print_array_api3($local_rc, $maxrow - 1, $col, @
output_array)\n";

#return ($local_rc, $maxrow - 1, $col, \@output_array);
return ($maxrow - 1, $col, \@output_array);
}   # end set_print_array_api3


#--------------------------------------------------------------------#
# set_print_array_api:                                               #
#   Convert the data contained in the reference to a 2-D array, of   #
#   the format required to call the set_display routine from the     #
#   CT::CT print facility.                                           #
#                                                                    #
# Parameters:                                                        #
#   $column_headers - array of column header names to appear in the  #
#                  first row of the output array.                    #
#   $row_header  - array of row header names to be used for long     #
#                  format display.                                   #
#   $title        - title for the display                            #
#   $data_array   - reference to an input array of lsrsrc-api format #
#                                                                    #
# Returns:                                                           #
#   $row_count    - number of rows in the output array.              #
#   $col_count    - number of rows in the output array.              #
#   $output_array - reference to the newly created array of data.    #
#--------------------------------------------------------------------#
sub set_print_array_api
{
# Grab input parameters
my ($column_headers,
    $row_header,
    $title,
    $data_array) = @_;

# Set up local variables
my $at_name;
my $element;
my @output_array;
my $value;
my $col = 1;
my $row = 1;
$DELIMITER = "tvrtvrtvr";               # delimiter for lsrsrc-api commands

# Set title in the corner spot
$output_array[0][0] = $title;

# Set up the row header column for the array:

# Set up the other rows in the array
# First column is for the row header information
$col = 1;
$row = 1;

# set up the column header 
$i = 1;
foreach $at_name (@$column_headers) {
   $output_array[0][$i] = $at_name;
   $i++;
}

# only display if something in the data array
if ((scalar @$data_array) > 0) {

   $i = 1;
   foreach $line (@$data_array) {
      chomp($line);

      # parse the output
      #@attr_vals = split(/::/, $line);
      @attr_vals = split(/$DELIMITER/, $line);

      # if $line ends with the delimiter, then there's a null (or no value)
      # for the last attribute.  make sure it's kept.
      if ($line =~ /$DELIMITER$/) {
         $attr_vals[$#attr_vals+1] = "";
      }

      # put into array
      $output_array[$i][0] = $row_header." $i:";
      $j = 1;
      foreach $attr_val (@attr_vals) {

         # put output into the output array
         $output_array[$i][$j] = $attr_val;
         $j++;
      }

      # in case the split above skipped trailing delimiters (many had no values)
      # make sure enough "empty" slots are created (defect 110003)
      if ($#attr_vals < $#$column_headers) {
         for (my $k = $#attr_vals+1; $k <= $#$column_headers+1; $k++) {
             $output_array[$i][$k] = "";
             }
         }

      $i++;
   }
}

$row = $#output_array;
$col = scalar(@{$output_array[0]});

return ($row, $col, \@output_array);
}   # end set_print_array_api


#--------------------------------------------------------------------#
# getIMsg : calls $LSMSG to print out the message with the           #
#   required parameters, like printIMsg, except the message is       #
#   returned instead of printed.  Used for NLS.                      #
#                                                                    #
# Parameters:                                                        #
#   msg       in  Message mnemonic / message number in a sense.      #
#   optargs   in  Extra arguments/parameters to send to LSMSG.       #
#                                                                    #
# Returns:                                                           #
#   msgtext   out Array of messages.                                 #
#                                                                    #
# Global Variables:                                                  #
#   $main::Trace    in  Print extra info when trace is on.           #
#   $main::PROGNAME in  Calling program/command for error message.   #
#   $main::LSMSG    in  Path & Command to display messages.          #
#   $main::MSGCAT   in  The calling commands Message catalogue.      #
#--------------------------------------------------------------------#
sub getIMsg
{
my ($msg, @optargs) = @_;
my ($optarg, $optargs);
my @msgtext = ();

$main::Trace &&
    print STDERR "$main::LSMSG $main::PROGNAME $main::MSGCAT $msg @optargs\n";

# Keep the args to LSMSG separate by separating with single quotes
# but must replace internal single quotes with blanks or get an error.
# Must escape internal double quotes for the system call.
foreach $optarg (@optargs) {
    $optarg =~ s/'/ /g;
    $optarg =~ s/"/\\"/g;
}
$optargs = "'" . join("' '",@optargs) . "'";

if (scalar @optargs > 0) {
     @msgtext = `$main::LSMSG $main::PROGNAME $main::MSGCAT $msg $optargs`;
}
else {
     @msgtext = `$main::LSMSG $main::PROGNAME $main::MSGCAT $msg`;
}

return (@msgtext);
}   # end getIMsg


#--------------------------------------------------------------------#
# End File.                                                          #
#--------------------------------------------------------------------#
