# -*-perl-*-

# $Id: MachineStatus.plm,v 1.1 2006/01/10 21:28:32 thomas Exp $

# Deal with machine status configuration

=head1 NAME

What::MachineStatus - Deal with machine status configuration

=head1 SYNOPSIS

my $Stat = new What::MachineStatus (file => B<File-to-read>);

my $value = $Stat->find ($status);

my $value = $Stat->find ($status, $attr);

=head1 DESCRIPTION

B<What::MachineStatus> provides a central facility to deal
with machine statuses in what.  This facility provides for a set of
arbitrary attributes associated with an arbitrary set of machine
statuses.  The following methods are available:

=over 4

=cut

package What::MachineStatus;

use strict;
use XML::Simple;
use Data::Dumper;

###############################################################################

=item my $Stat = new What::MachineStatus (file => B<File-to-read>);

Create a new What::MachineStatus objhect for further
processing.  If a file is provided, use that instead of the default
machine stat file.

=cut

sub new
{
  my $invocant = shift;
  my %parms = @_;

  my $self = bless {} => (ref ($invocant) || $invocant);
  return undef unless defined $self;
  $self->{file} = defined ($parms{file})?$parms{file}:'/s/what-0.1.31/xml/MachineStatus.xml';

  # Make perl shut up about undefined values.
  # Load the data on the first query.
  $self->{mtime} = 0;

  $self;
}


###############################################################################

=item my $value = $Stat->find ();

Returns a hashref of hashrefs.  The outer hash ref is an index of
machine statuses defined in the config file.  The inner hash ref is a
hash of attribute, value pairs for each machine status.

=item my $value = $Stat->find ($status);

Returns a hashref of attribute, value pairs for the requested
B<status>, or undef if the B<status> does not exist in the definition
file.

=item my $value = $Stat->find ($status, $attr);

Returns a scalar attribute value for the requested B<status> and
B<attribute>, or B<undef> if either do not exist.

=cut

sub find
{
  my $self = shift;

  $self->check_reload;

  if (@_ == 0) {
    # Give them the whole data
    return $self->{data};
  }

  my $status = shift;
  if (@_ == 0) {
    # Return all attributes for the given machine status
    return (exists $self->{data}->{$status})?$self->{data}->{$status}:undef;
  }

  my $attr = shift;
  return (exists $self->{data}->{$status}->{$attr})
    ?$self->{data}->{$status}->{$attr}:undef;
}


###############################################################################

# Check and reload the machine status data

sub check_reload
{
  my $self = shift;

  my $mtime = (stat $self->{file})[9];
  return if $mtime == $self->{mtime};
  $self->{mtime} = $mtime;

  $self->{data} = XMLin ($self->{file});
  # OK.  So it would realy, _really_ suck to have the XMLin fail and hand
  # back a data structure that didn't say to keep the host attributes
  # for something like Production hosts, or that said to not generate
  # configs for Production hosts.  Do some sanity checking on the data,
  # and EXIT THE PROGRAM if there's a problem.
  die "Failed to load MachineStatus data! (this is _really_ bad!)"
    unless defined ($self->{data});

  # Ignore the man behind the curtain!  I am the great and pow..er..ful...
  $self->{data} = {%{$self->{data}->{status}}};

  die "MachineStatus data integrity problem! (this is _really_ bad!)"
    unless $self->{data}->{Production}->{SaveHostAttributes} =~ /^(true|on|yes|1)$/i;

  # Turn booleans into numeric booleans
  my ($status, $attr);
  foreach $status (keys %{$self->{data}}) {
    foreach $attr (keys %{$self->{data}->{$status}}) {
      $self->{data}->{$status}->{$attr}
	= ($self->{data}->{$status}->{$attr} =~ /^(true|on|yes|1)$/i)?1:0;
    }
  }
}


###############################################################################

# Finish docs

=back

=head1 FILES

B</s/what-0.1.31/xml/MachineStatus.xml> - XML document containing machine statuses

=cut

###############################################################################

1;
