#------------------------------------------------------------
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------

#------------------------------------------------------------
# Validation Rule Key Value List Object.  Extends the Validate
# Rule class.  This object contains the method to do validation
# on piece of data.
#
# Determine if a field contains a valid key value pair list.
# keys and values are delimeted by an '=' and pairs by ';' by
# default.
#
# Parameter Requirement:
#
#    The parameter used in config_rule must be a:
#
# Base Class:
#   Validation::Rule
#
# Public methods:
#   + Validate::Rule::Code new();
#   + $fail_status         ok();
#   + $scalar              AUTOLOAD( $scalar );
#------------------------------------------------------------
package Validate::Rule::Constraint::KeyValueList;
use strict;

use lib '/app/tools/common/lib';
use Common::Log;
use Common::RSApp;
use Common::Assert;

use lib '/app/tools/metadata/lib';
use base 'Validate';
use base 'Validate::Rule';

use vars qw($AUTOLOAD);

###
# Define addition public accessors
###
use constant kClassAttributes => qw( message parameter fail_status );

###
# Default failure message if the OK method fails.
###
use constant kFailureMessage => "Key value list not properly formatted";

###
# Default field seperator
###
use constant kDefaultFieldSeperator => '=';

###
# Default record seperator
###
use constant kDefaultRecordSeperator => ';';

sub ok {
    my $self  = shift;
    my $value = shift;

    my $fail =
      defined( $self->{_fail_status} )
      ? $self->{_fail_status}
      : Validate::kStatusDefault;
    my $success = Validate::kStatusOK;

    return undef unless ( $self->is_configured() );

    return $success unless ( defined($value) );

    my $fs = kDefaultFieldSeperator;
    my $rs = kDefaultRecordSeperator;

    # Make sure we have an even sized list of keys and values
    my @fields = $self->_dataAsList($value);

    # Make sure there aren't any empty fields
    foreach (@fields) {
        s/^\s+//;
        s/\s+$//;
        return $fail unless ( $_ && length($_) );
    }

    # If the split failed we fail
    return $fail if ( $value && !@fields );

    return @fields % 2 == 0 ? $success : $fail;
}

#------------------------------------------------------------
# Private Methods
#------------------------------------------------------------

sub _dataAsList {
    my $self = shift;
    my $value = shift || return;

    my $fs = kDefaultFieldSeperator;
    my $rs = kDefaultRecordSeperator;

    my @list = split( /\s*[$fs$rs]\s*/, $value );

    Common::Log::Debug( "Key Values: " . join( ", ", @list ) );

    return @list;
}

#------------------------------------------------------------
# Validate::Rule _init()
# Initialize the object.
#
# - Build accessor method hash
# - set internal private data ( message, fail_status, and
#   parameter ). See the base class for parameter defintions.
#
#------------------------------------------------------------
sub _init {
    my ( $self, %args ) = @_;

    # Build a hash with our valid class attributes
    foreach ( (kClassAttributes) ) {
        $self->{_attributes}->{$_}++;
    }

    $self->message( $args{message}                    ? $args{message}     : kFailureMessage );
    $self->fail_status( defined( $args{fail_status} ) ? $args{fail_status} : Validate::kStatusDefault );
    $self->parameter( $args{parameter} ) if ( $args{parameter} );

    $self->SUPER::_init(%args);

    return $self;
}
1;
