/usr/local/CPAN/Xmldoom/Xmldoom/Criteria/Comparison.pm
package Xmldoom::Criteria::Comparison;
use Xmldoom::Criteria;
use DBIx::Romani::Query::Where;
use DBIx::Romani::Query::Comparison;
use strict;
use Data::Dumper;
sub new
{
my $class = shift;
my $args = shift;
my $lval;
my $rval;
my $type;
if ( ref($args) eq 'HASH' )
{
$lval = $args->{lval};
$rval = $args->{rval};
$type = $args->{type};
}
else
{
$lval = $args;
$rval = shift;
$type = shift;
}
if ( not defined $type )
{
$type = $Xmldoom::Criteria::EQUAL;
}
if ( ref($rval) ne 'ARRAY' )
{
if ( defined $rval )
{
$rval = [ $rval ];
}
else
{
$rval = [ ];
}
}
my $rval_count = scalar @$rval;
# validate the number of rvals
if ( $type eq $Xmldoom::Criteria::BETWEEN )
{
if ( $rval_count != 2 )
{
# Programmer Error
die "BETWEEN comparisons must have 2 rvals";
}
}
elsif ( $type eq $Xmldoom::Criteria::IN or
$type eq $Xmldoom::Criteria::NOT_IN )
{
if ( $rval_count < 2 )
{
# Programmer Error
die "IN comparisons must have at least 2 rvals";
}
}
elsif ( $type eq $Xmldoom::Criteria::IS_NULL or
$type eq $Xmldoom::Criteria::IS_NOT_NULL )
{
if ( $rval_count != 0 )
{
# Programmer Error
die "IS NULL and IS NOT NULL comparisons cannot have any rvals";
}
}
elsif ( $rval_count != 1 )
{
# Programmer Error
die "Comparison '$type' must have 1 and only 1 rval";
}
my $self = {
lval => $lval,
rval => $rval,
type => $type,
};
bless $self, $class;
return $self;
}
sub get_lval { return shift->{lval}; }
sub get_rval { return shift->{rval}; }
sub get_type { return shift->{type}; }
sub get_query_lval
{
my ($self, $database) = @_;
return $self->get_lval()->get_query_lval( $database );
}
sub get_query_rval
{
my ($self, $database, $lval) = @_;
my $multis = (scalar @{$self->get_rval()} > 1);
my @rvals;
foreach my $rval ( @{$self->get_rval()} )
{
if ( $multis and not $rval->isa( 'Xmldoom::Criteria::Literal' ) )
{
die "Cannot have multiple rvalues that aren't literals";
}
push @rvals, $rval->get_query_rval( $database, $self->get_lval() );
}
return \@rvals;
}
sub generate
{
my ($self, $database) = @_;
my $lval_list = $self->get_query_lval( $database );
my $rval_list = $self->get_query_rval( $database );
my $where = DBIx::Romani::Query::Where->new( $DBIx::Romani::Query::Where::AND );
# turn our list of lvals into a list of operators
foreach my $lval ( @$lval_list )
{
my $op;
$op = DBIx::Romani::Query::Comparison->new( $self->get_type() );
$op->add( $lval );
$where->add( $op );
}
# Ok, this makes no sense. Don't even try to understand it unless
# your were recently elected Christ and Buddah was ecstatic that you
# knew his name.
foreach my $rvals ( @$rval_list )
{
if ( scalar @$rvals != scalar @{$where->get_values()} )
{
die "Must have an equal number of lvalues and rvalues in a Comparison.";
}
foreach my $rval ( @$rvals )
{
foreach my $op ( @{$where->get_values()} )
{
$op->add( $rval );
}
}
}
# reduce me, baby.
if ( scalar @{$where->get_values()} == 1 )
{
# if there is only one, then return only that
return $where->get_values()->[0];
}
return $where;
}
sub get_tables
{
my ($self, $database) = @_;
my @tables;
foreach my $table_name ( @{$self->get_lval()->get_tables( $database )} )
{
push @tables, $table_name;
}
# rval's only go into the from_table list
foreach my $rval ( @{$self->get_rval()} )
{
foreach my $table_name ( @{$rval->get_tables( $database )} )
{
push @tables, $table_name;
}
}
return \@tables;
}
sub clone
{
my $self = shift;
#my $lval = $self->get_lval()->clone();
#my @rval = map { $_->clone() } @{$self->get_rval()};
#return Xmldoom::Criteria::Comparison->new( $lval, \@rval, $self->get_type() );
return Xmldoom::Criteria::Comparison->new( $self->get_lval(), $self->get_rval(), $self->get_type() );
}
1;