#!/usr/bin/perl
# This is the test harness for the XML library for MAGv3 implementation.

# First part of this script show basic XML function that search and display an element value.
# Second part is the library for all XML based operation
#
# Input: MAG.xml
# Processing: Search and display all Model Guidance type model that cover namer
# Output: Stdout
#
# Lin Gan 03202013
# Paula Freeman 3/2016 This was commented out code in the magv3-xml-library.pl library.
#                      I pulled it out, removed the comments, and stored it here.  I
#                      have not tested it.

  use strict;
  use warnings;

## dec sub
  sub find_model_by_area;
  sub trim($);
  

# set target file name
  my $filename = 'MAG.xml';


 use XML LibXML package
 use XML::LibXML;


 Set area to look for
 my $area   = 'namer';


# Structure Construction
  my $parser = XML::LibXML->new();


# Read in XMl file and Organize the document
  my $doc    = $parser->parse_file($filename);

# Found all model name in a type that cover the target area
# 	such as (Model Guidance type for namer) or (Observations type for samer)   
  my @found_models_by_type_area_resultset_list;

# Check to see if input model name is valid name; return 1 if model is defined, invalid return 0 
  my $is_model_name_valid = 0;

#   get_max_time: Get the max time for this model
  my $max_time_of_model_name;

#   get_max_threads: Get the max threads for this model
  my $max_threads_of_model_name;

#   get_filepathpats: Get the input file path patterns.
  my @filepathpats_of_model_name;

#   get_cycle_filepathpats: Get the input file path patterns for this cycle, if defined
  my @filepathpats_of_model_name;

#   get areas for this model name
  my @found_areas_by_model_resultset_list;

#   get params for this model name
  my @found_parameters_by_model_resultset_list;

#   get forecast hour ranges for this model name
  my @found_forecast_ranges_resultset_list;

#   get scripts for this model name
  my $found_scripts_name;

#   get exception for this model and param
  my @found_exceptions_resultset_list;


  
# Show all model that cover namer area (Worked)
# Set query

# Working for list all model cover namer from the demo version (deprecated)
# my $query  = "/tns:mag/tns:models/tns:model/tns:areas/tns:area/tns:name[text()='$area']/../../../tns:name/text()";

# Refine search to include just Model Guidance (worked for current XML version 2)
my $query  = "/tns:mag/tns:models/tns:model/tns:description[text()='Model Guidance']/../tns:areas/tns:area/tns:name[text()='$area']/../../../tns:name/text()";

# Search and Print result
print $_->data . "\n" foreach ($doc->findnodes($query));


print " \n";
print "Above are the results show all models in Model Guidance that cover namer. \n";
print "---------------------------------------------------------------- \n";





# Calling XML library to list all models in Model Guidance cover namer
print " \n";
print "XML operation Lib: find_model_by_area \n";
print "Usage one: \n";
print "Looking for all Model Guidance type of models that cover namer.    Starting... \n";

	@found_models_by_type_area_resultset_list = find_model_by_area ($doc, 'namer', 'Model Guidance');

print "Done! \n";
print "---------------------------------------------------------------- \n";

# Calling XML library to list all models in Observations and Analyses cover namer
print " \n";
print "XML operation Lib: find_model_by_area \n";
print "Usage two: \n";
print "Looking for all Observations and Analyses type of models that cover samer.    Starting... \n";

	@found_models_by_type_area_resultset_list = find_model_by_area ($doc, 'samer', 'Observations and Analyses');

print "Done! \n";
print "---------------------------------------------------------------- \n";

# Calling XML library to list all models in Model Guidance cover namer
print " \n";
print "XML operation Lib: valid_model \n";
print "Validating client model name input.    Starting... \n";
	my $client_input_model_name = 'HRW-NMMB-WUS';
#$is_model_name_valid = valid_model($doc, $client_input_model_name);
#
print "Validate result is: $is_model_name_valid \n";
print "Done! \n";
print "---------------------------------------------------------------- \n";

# Query XML to get max time on a given model
print " \n";
print "XML operation Lib: get_max_time \n";
print "Query XML to get max time on a given model name.    Starting... \n";
	my $client_input_model_name_maxtime = 'nam';
#$max_time_of_model_name = get_max_time($doc, $client_input_model_name_maxtime);
#
print "The MAX time is: $max_time_of_model_name \n";
print "Done! \n";
print "---------------------------------------------------------------- \n";

# Query XML to get max threads on a given model
print " \n";
print "XML operation Lib: get_max_threads \n";
print "Query XML to get max threads on a given model name.    Starting... \n";
	my $client_input_model_name_threads = 'polar';
#$max_threads_of_model_name = get_max_threads($doc, $client_input_model_name_threads);
#
print "The MAX Threads is: $max_threads_of_model_name \n";
print "Done! \n";
print "---------------------------------------------------------------- \n";



# Query XML to get file path on a given model
print " \n";
print "XML operation Lib: get_filepathpats \n";
print "Query XML to get array of file path on a given model name.    Starting... \n";
	my $client_input_model_name_filepathpats = 'GEFS-MNSPRD';
#@filepathpats_of_model_name = get_filepathpats($doc, $client_input_model_name_filepathpats, $COMIN);
#
print "Done! \n";
print "---------------------------------------------------------------- \n";

# Query XML to get cycle file paths for a given model and cycle
print " \n";
print "XML operation Lib: get_cycle_filepathpats \n";
print "Query XML to get array of file path on a given model name.    Starting... \n";
	my $client_input_model_name_filepathpats = 'GEFS-MNSPRD';
@filepathpats_of_model_name = get_cycle_filepathpats($doc, $client_input_model_name_filepathpats, $cycle, $COMIN);
	
print Done! \n";
print ---------------------------------------------------------------- \n";


# Query XML to get area list on a given model
print " \n";
print "XML operation Lib: get_areas_by_model_name \n";
print "Query XML to get array of areas on a given model name.    Starting... \n";
	my $client_input_model_name_getareas = 'NAM';
@found_areas_by_model_resultset_list = get_areas_by_model_name($doc, $client_input_model_name_getareas);

print "Done! \n";
print "---------------------------------------------------------------- \n";


# Query XML to get area list on a given model
print " \n";
print "XML operation Lib: get_areas_by_model_name \n";
print "Query XML to get array of areas on a given model name.    Starting... \n";
	my $client_input_model_name_getareas = 'NAM';
@found_areas_by_model_resultset_list = get_areas_by_model_name($doc, $client_input_model_name_getareas);

print "Done! \n";
print "---------------------------------------------------------------- \n";


# Query XML to get parameter list on a given model
print " \n";
print "XML operation Lib: get_params_by_model_name \n";
print "Query XML to get array of parameters on a given model name.    Starting... \n";
	my $client_input_model_name_for_parameters_list = 'gefs-spag';
@found_parameters_by_model_resultset_list = get_params_by_model_name($doc, $client_input_model_name_for_parameters_list);
	
print "Done! \n";
print "---------------------------------------------------------------- \n";


# Query XML to get forecast hours list on a given model
print " \n";
print "XML operation Lib: get_fhr_ranges_by_model_name \n";
print "Query XML to get array of forecast hours on a given model name.    Starting... \n";
	my $client_input_model_name_for_forecast_hr_list = 'gefs-spag';
@found_forecast_ranges_resultset_list = get_fhr_ranges_by_model_name($doc, $client_input_model_name_for_forecast_hr_list);
	
print "Done! \n";
print "---------------------------------------------------------------- \n";


# Query XML to get script list on a given model
print " \n";
print "XML operation Lib: get_script_by_model_name \n";
print "Query XML to get array of script on a given model name.    Starting... \n";
	my $client_input_model_name_for_script_list = 'gfs';
	my $client_input_parameter_for_script_list = 'all';
	$found_scripts_name = get_script_by_model_name($doc, $client_input_model_name_for_script_list, $client_input_parameter_for_script_list);

print "The script is: $found_scripts_name \n";	
print "Done! \n";
print "---------------------------------------------------------------- \n";


# Query XML to get exception list on a given model and param
print " \n";
print "XML operation Lib: get_area_exception_by_name_param \n";
print "Query XML to get array of exception on a given model name and param.    Starting... \n";
	my $client_input_model_name_for_exception_list = 'nam';
	my $client_input_area_for_exception_list = 'all';
	my $client_input_parameter_for_exception_list = 'precip_p36';
	@found_exceptions_resultset_list = get_area_exception_by_name_param($doc, $client_input_model_name_for_exception_list, $client_input_area_for_exception_list, $client_input_parameter_for_exception_list);
	
print "Done! \n";
print "---------------------------------------------------------------- \n";


# Sub to get the list of models that has input area coverage
# Input: XML object, 
#		 name of the area looking for (namer, samer...), 
#		 model type (Model Guidance, Observations and Analyses, or Tropical Guidance)
# Process: Query the XML and get a list of matching model in the target model type
# Output: Array of string
# Usage: find_model_by_area ($doc, 'namer', 'Model Guidance');
#
# 03202013
# Lin Gan 

sub find_model_by_area {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input area name
	my $inparea = shift;
	
	#	input model type
	my $modeltype = shift;
	
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_model_name;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Setup query string
	my $find_model_by_area_query  = "/tns:mag/tns:models/tns:model/tns:description[text()='$modeltype']/../tns:areas/tns:area/tns:name[text()='$inparea']/../../../tns:name/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_model_by_area_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_model_name = $individual_result_node->string_value();
	
	#	Construct linked list
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}
	
# Sub to validate client input model name vs XML record
# Input: model name, 
# Process: validate the model name; return 1 if model is defined, invalid return 0 
# Output: 1 or 0
# Usage: valid_model ($doc, 'gfs');
#
# 03212013
# Lin Gan 

sub valid_model {

    #	input XML node
	my $inpdoc = shift;
	
	#	input model type
	my $client_input_model_name = shift;
	
	#	Validated return result
	my $validated_result=0;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $model_name;
	
	#	Error handling
	return unless defined $inpdoc;

	#	Convert input to uppercase string and trim it
	$client_input_model_name = trim(uc($client_input_model_name));
	
	#	Setup query string
	my $get_all_model_name_query  = "/tns:mag/tns:models/tns:model/tns:name/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($get_all_model_name_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get each matching model name from XML
		$model_name = $individual_result_node->string_value();
	
	#	validate against client input
		if ($client_input_model_name eq $model_name){
			$validated_result = 1;
			return $validated_result;
		}
		
		
	}
	return 0;	
}



sub trim($)
{
	my $string = shift;
	$string =~ s/^\s+//;
	$string =~ s/\s+$//;
	return $string;
}


# Sub to get max time for the given model name; assume the name is passed check with valid_model
# Input: model name, 
# Process: get maxtime from model name 
# Output: maxtime value
# Usage: get_max_time ($doc, 'gfs');
#
# 03212013
# Lin Gan 

sub get_max_time {

    #	input XML node
	my $inpdoc = shift;
	
	#	input model type
	my $client_input_model_name = shift;
	
	#	Validated return result
	my $maxtime_result='';
	
	#	XML query result nodes
	my $resultset_nodes;
	
	#	Error handling
	return unless defined $inpdoc;

	#	Convert input to uppercase string and trim it
	$client_input_model_name = trim(uc($client_input_model_name));
	
	#	Setup query string
	my $get_all_model_name_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:max-time/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($get_all_model_name_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get each matching model name from XML
		$maxtime_result = $individual_result_node->string_value();
		
	}
	return $maxtime_result;	
}


# Sub to get max threads for the given model name; assume the name is passed check with valid_model
# Input: model name, 
# Process: get threads from model name 
# Output: threads value
# Usage: get_max_threads ($doc, 'gfs');
#
# 03212013
# Lin Gan 

sub get_max_threads {

    #	input XML node
	my $inpdoc = shift;
	
	#	input model type
	my $client_input_model_name = shift;
	
	#	Validated return result
	my $threads_result='';
	
	#	XML query result nodes
	my $resultset_nodes;
	
	#	Error handling
	return unless defined $inpdoc;

	#	Convert input to uppercase string and trim it
	$client_input_model_name = trim(uc($client_input_model_name));
	
	#	Setup query string
	my $get_all_model_name_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:max-threads/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($get_all_model_name_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get each matching model name from XML
		$threads_result = $individual_result_node->string_value();
		
	}
	return $threads_result;	
}



# Sub to get array of filepath for given model
# Input: xmldoc, model name, COMIN
# Process: get array of filepath from model name 
# Output: array of path name
# Usage: get_filepathpats ($doc, 'gfs', $COMIN);
#
# 03212013
# Lin Gan 

sub get_filepathpats {

    #	Final result set list
    my @inputpat_array_result =();
    
    #	input XML node
	my $inpdoc = shift;
	
	#	input model type
	my $client_input_model_name = shift;

        #       COMIN value
        #
        my $COMIN = shift;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_file_path_name;
	
	#	Error handling
	return unless defined $inpdoc;

	#	Convert input to uppercase string and trim it
	$client_input_model_name = trim(uc($client_input_model_name));
	
	#	Setup query string
	# my $get_all_model_name_query  = "/tns:mag/tns:models/tns:model/tns:input-pat/text()/../tns:name[text()='$client_input_model_name']";
	my $get_all_model_name_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:input-pat/text()";
	
#	/tns:mag/tns:models/tns:model/tns:description[text()='$modeltype']/../tns:areas/tns:area/tns:name[text()='$inparea']/../../../tns:name/text()

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($get_all_model_name_query);


	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_file_path_name = $individual_result_node->string_value();

        #       Replace '$COMIN' with $COMIN value
        
                $individual_file_path_name =~ s/COMIN/$COMIN/;

	
	#	Construct linked list
		push (@inputpat_array_result,  $individual_file_path_name);
		
	}
	return @inputpat_array_result;
	
}

# Sub to get array of filepaths for given model
# Input: xmldoc, model name, COMIN
# Process: get array of filepaths from model name
# Output: hash of cycles that each point to an array of path names
# Usage: get_cycle_filepathpats ($doc, 'gfs', $COMIN);
#
# 2/23/2016
# Paula Freeman

sub get_cycle_filepathpats {

    # Final result set list
    my %hash_result =();
    
    # input XML node
    my $inpdoc = shift;
	
    # input model type
    my $model_name = shift;

    #  COMIN value
    my $COMIN = shift;
	
    # XML query result nodes
    my $resultset_cycle_nodes;
    my $resultset_filepat_nodes;

    # Each individual result node	
    my $filepat;
	
    # Error handling
    return unless defined $inpdoc;

    # Convert model to uppercase string and trim it
    $model_name = trim(uc($model_name));

    #<tns:cycle-input-pats>
    #         <tns:cycle>
    #                 <tns:name>00</tns:name>
    #                 <tns:input-pat>COMIN/hiresw.YYYYMMDD/hiresw_conusnmmb_YYYYMMDDCCfFFF</tns:input-pat>
    #                 <tns:input-pat>COMIN/hiresw.YYYYMMDD/hiresw_guamnmmb_YYYYMMDDCCfFFF</tns:input-pat>
    #                 <tns:input-pat>COMIN/hiresw.YYYYMMDD/hiresw_hinmmb_YYYYMMDDCCfFFF</tns:input-pat>
    #         </tns:cycle>
    # ...
	
    # Setup query string to get the cycles, if defined
    my $query_cycles  = "/tns:mag/tns:models/tns:model/tns:name[text()='$model_name']/../tns:cycle-input-pats/tns:cycle/tns:name/text()";

	
    # Start cycles query 
    $resultset_cycle_nodes = $inpdoc->findnodes($query_cycles);

    # iterate over resultset
    
    foreach my $cycle_node ($resultset_cycle_nodes->get_nodelist) {
		
       #  Get string value for debugging purpose
	
       my $cycle_name = $cycle_node->string_value();

       # Get filepat for this cycle
           
       my $query_pats  = "/tns:mag/tns:models/tns:model/tns:name[text()='$model_name']/../tns:cycle-input-pats/tns:cycle/tns:name[text()='$cycle_name']/../tns:input-pat/text()";

       # Start filepat query 
	   
       $resultset_filepat_nodes = $inpdoc->findnodes($query_pats);

       # iterate over resultset
       #
       my @array_result=();
       
       foreach my $filepat_node ($resultset_filepat_nodes->get_nodelist) {

	  # Get string value
	  #
	  $filepat = $filepat_node->string_value();

          # Replace '$COMIN' with $COMIN value
        
          $filepat =~ s/COMIN/$COMIN/;

          # add to array
          
	  unshift (@array_result,  $filepat);
      }
      $hash_result{$cycle_name}= \@array_result;
         		
   }

   return %hash_result;
	
}


# Sub to get the list of area for given model name
# Input: XML object, 
#		 name of the model (nam,gfs...)
# Process: Query the XML and get a list of areas
# Output: Array of string
# Usage: get_areas_by_model_name ($doc, 'gfs');
#
# 03222013
# Lin Gan 

sub get_areas_by_model_name {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	Convert input to uppercase string and trim it
	my $client_input_model_name = trim(uc($inpmodel));
		
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_area_name;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Setup query string
	my $find_area_by_model_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:areas/tns:area/tns:name/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_area_by_model_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_area_name = $individual_result_node->string_value();
	
	#	Construct linked list
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}


# Sub to get the list of parameters for given model name
# Input: XML object, 
#		 name of the model (nam,gfs...)
# Process: Query the XML and get a list of parameters
# Output: Array of string
# Usage: get_params_by_model_name ($doc, 'gfs');
#
# 03222013
# Lin Gan 

sub get_params_by_model_name {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	Convert input to uppercase string and trim it
	my $client_input_model_name = trim(uc($inpmodel));
		
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_param_name;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Setup query string
	my $find_parameters_by_model_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:products/tns:product/tns:name/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_parameters_by_model_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_param_name = $individual_result_node->string_value();
	
	#	Construct linked list
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}



# Sub to get the list of forecast hours for given model name
# Input: XML object, 
#		 name of the model (nam,gfs...)
# Process: Query the XML and get a list of forecast hours
# Output: Array of string
# Usage: get_fhr_ranges_by_model_name ($doc, 'gfs');
#
# 03222013
# Lin Gan 

sub get_fhr_ranges_by_model_name {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	Convert input to uppercase string and trim it
	my $client_input_model_name = trim(uc($inpmodel));
		
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_forecast_hour;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Setup query string
	my $find_forecast_hr_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:forecast-hours/tns:range/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_forecast_hr_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_forecast_hour = $individual_result_node->string_value();
	
	#	Construct linked list
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}


# Sub to get the script list of model and parameter
# Input: XML object, 
#		 model name (gfs, nam...), 
#		 parameter name (all, precip_p03...)
# Process: Query the XML and get a list of script
# Output: Array of string
# Usage: get_script_by_model_name ($doc, 'gfs', 'all');
#
# 03202013
# Lin Gan 

sub get_script_by_model_name {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input area name
	my $inpmodel = shift;
	
	#	input model type
	my $inpparameter = shift;
	
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_script_name="";
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Format model name input
	my $client_input_model_name = trim(uc($inpmodel));
	
	#	Format parameter input
	$inpparameter = trim(lc($inpparameter));
	
	#	Setup query string
	my $find_script_by_m_p_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:scripts/tns:$inpparameter/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_script_by_m_p_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_script_name = $individual_result_node->string_value();
	
		
	}
	return $individual_script_name;	
}



# Sub to get the exception list of model and parameter
# Input: XML object, 
#		 model name (gfs, nam...), 
#		 area (all, polar)
#		 parameter name (all, precip_p03...)
# Process: Query the XML and get a list of exceptions
# Output: Array of string
# Usage: get_script_by_model_name ($doc, 'gfs', 'all', 'precip_p06');
#
# 03222013
# Lin Gan 

sub get_area_exception_by_name_param {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	input area name
	my $inparea = shift;	
	
	#	input param name
	my $inpparameter = shift;
	
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_exception_name;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Format model name input
	my $client_input_model_name = trim(uc($inpmodel));

	#	Format area input
	$inparea = trim(lc($inparea));
	
	#	Format parameter input
	$inpparameter = trim(lc($inpparameter));
	
	#	Setup query string
	my $find_exception_by_m_p_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:products/tns:product/tns:name[text()='$inpparameter']/../tns:exceptions/tns:$inparea/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_exception_by_m_p_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_exception_name = $individual_result_node->string_value();
	
		
	#	Construct linked list
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}

# Sub to get the number of cycles to process for this model.
# Input: model name, 
# Process: get cycles-to-process from model name 
# Output: cycles-to-process value
# Usage: get_model_cycles_to_process ($doc, 'gfs');
#
# 11/25/2015  Paula Freeman

sub get_model_cycles_to_process {

    #	input XML node
	my $inpdoc = shift;
	
	#	input model type
	my $client_input_model_name = shift;
	
	#	Validated return result
	my $result='';
	
	#	XML query result nodes
	my $resultset_nodes;
	
	#	Error handling
	return unless defined $inpdoc;

	#	Convert input to uppercase string and trim it
	$client_input_model_name = trim(uc($client_input_model_name));
	
	#	Setup query string
	my $query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:cycles-to-process/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get each matching model name from XML
		$result = $individual_result_node->string_value();
		
	}
	return $result;	
}


# Sub to get the model string used in gif files for the given model name; assume the name is passed check with valid_model
# Input: model name, 
# Process: get model-in-filename from model name 
# Output: model-in-filename value
# Usage: get_max_threads ($doc, 'gfs');
#
# 04/27/2014  Paula Freeman

sub get_model_in_filename {

    #	input XML node
	my $inpdoc = shift;
	
	#	input model type
	my $client_input_model_name = shift;
	
	#	Validated return result
	my $mif_result='';
	
	#	XML query result nodes
	my $resultset_nodes;
	
	#	Error handling
	return unless defined $inpdoc;

	#	Convert input to uppercase string and trim it
	$client_input_model_name = trim(uc($client_input_model_name));
	
	#	Setup query string
	my $get_all_mif_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:model-in-filename/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($get_all_mif_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get each matching model name from XML
		$mif_result = $individual_result_node->string_value();
		
	}
	return $mif_result;	
}


sub  get_image_size_model_area {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	input area name
	my $inparea = shift;	

	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_exception_name;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Format model name input
	my $client_input_model_name = trim(uc($inpmodel));

	#	Format area input
	$inparea = trim(lc($inparea));
	
	
	#	Setup query string
        my $query_for_image_size = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:areas/tns:area/tns:name[text()='$inparea']/../tns:sizes/text()";


	#	Start query
	$resultset_nodes = $inpdoc->findnodes($query_for_image_size);

        my @list=($resultset_nodes->get_nodelist);

	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_exception_name = $individual_result_node->string_value();
	}
	return $individual_exception_name;
}


# Sub to get the fmins field for a model and parameter
# Input: XML object, 
#		 model name (gfs, nam...), 
#		 parameter name (all, precip_p03...)
# Process: Query the XML and get a list of exceptions
# Output: Array of string
# Usage: get_fmins_by_name_param ($doc, 'gfs', 'precip_p06');
#
# 04/29/2015 Paula Freeman

sub get_fmins_by_model_param {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	input param name
	my $inpparameter = shift;
	
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_exception_name;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Format model name input
	my $client_input_model_name = trim(uc($inpmodel));

	#	Format parameter input
	$inpparameter = trim(lc($inpparameter));
	
	#	Setup query string
	my $find_fmins_by_m_p_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:products/tns:product/tns:name[text()='$inpparameter']/../tns:fmins/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_fmins_by_m_p_query);
	
	#	iter resultsets
	my $individual_result_name="";
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_result_name = $individual_result_node->string_value();
		
	}
	return $individual_result_name;
}
# Sub to get the list of cycles given model name
# Input: XML object, 
#		 name of the model (nam,gfs...)
# Process: Query the XML and get a list valid cycles
# Output: Array of string
# Usage: get_cycles_by_model_name ($doc, 'gfs');
#
# 8/19/2015 
# Paula Freeman

sub get_cycles_by_model_name {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;
	
	#	Convert input to uppercase string and trim it
	my $client_input_model_name = trim(uc($inpmodel));
		
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_forecast_hour;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Setup query string
	my $find_cycle_query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:cycles/tns:cycle-time/text()";

	#	Start query
	$resultset_nodes = $inpdoc->findnodes($find_cycle_query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_forecast_hour = $individual_result_node->string_value();
	
	#	Construct linked list
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}

# Sub to get the list of cycles for a given model and area name 
# Input: XML object, 
#		 name of the model (nam,gfs...)
# Process: Query the XML and get a list valid cycles for the model area
#          If defined, this will override the cycles defined for
# Output: Array of string
# Usage: get_cycles_by_model_area_name ($doc, 'gfs', 'namer');
#
# 2/08/2016 
# Paula Freeman

sub get_cycles_by_model_area_name {

	#	Final result set list
    my @found_resultset_list =();
    
	#	input XML node
	my $inpdoc = shift;
	
	#	input model name
	my $inpmodel = shift;

	#	input area name
	my $inparea = shift;
	
	
	#	Convert input to uppercase string and trim it
	my $client_input_model_name = trim(uc($inpmodel));
	my $client_input_area_name = trim($inparea);
		
	#	Return array
	my $resultset_array;
	
	#	XML query result nodes
	my $resultset_nodes;

	#	Each individual result node	
	my $individual_cycle_hour;
	
	#	Error handling
	return unless defined $inpdoc;
	
	#	Setup query string
	my $query  = "/tns:mag/tns:models/tns:model/tns:name[text()='$client_input_model_name']/../tns:areas/tns:area/tns:name[text()='$client_input_area_name']/../tns:valid-cycles/tns:cycle-time/text()";


	#	Start query
	$resultset_nodes = $inpdoc->findnodes($query);
	
	#	iter resultsets
	foreach my $individual_result_node ($resultset_nodes->get_nodelist) {
		
	#	Get string value for debugging purpose
		$individual_cycle_hour = $individual_result_node->string_value();
	
		push (@found_resultset_list, $individual_result_node->string_value());
		
	}
	return @found_resultset_list;	
}


1;
