package Xmldoom::Definition::Property::Simple; use base qw(Xmldoom::Definition::Property); use strict; use Data::Dumper; sub new { my $class = shift; my $args = shift; my $parent; my $prop_name; my $attr_name; my $trans_to; my $trans_from; my $set_name; my $get_name; my $options; my $options_table; my $options_column; my $options_criteria; my $inclusive; if ( ref($args) eq 'HASH' ) { $parent = $args->{parent}; $prop_name = $args->{name}; $attr_name = $args->{attribute}; $trans_to = $args->{trans_to}; $trans_from = $args->{trans_from}; $set_name = $args->{set_name}; $get_name = $args->{get_name}; $options = $args->{options}; $options_table = $args->{options_table}; $options_column = $args->{options_column}; $options_criteria = $args->{options_criteria}; $inclusive = $args->{inclusive}; } else { $parent = $args; $prop_name = shift; $attr_name = shift; # if you don't know, then there is no need to know. $args = { parent => $parent, name => $prop_name, }; } # allow a short form when we want the property name # to be the same as the attribute name. if ( not defined $attr_name ) { $attr_name = $prop_name; } # TODO: use the $parent variable to check if we are creating a valid # property with a valid attribute. # the default get/set names if ( not defined $set_name ) { $set_name = "set_$prop_name"; } if ( not defined $get_name ) { $get_name = "get_$prop_name"; } # init our members my $self = $class->SUPER::new( $args ); $self->{attr_name} = $attr_name; $self->{trans_to} = $trans_to; $self->{trans_from} = $trans_from; $self->{set_name} = $set_name; $self->{get_name} = $get_name; $self->{options} = $options || [ ]; $self->{options_table} = $options_table; $self->{options_column} = $options_column; $self->{options_criteria} = $options_criteria; $self->{inclusive} = $inclusive || 0; bless $self, $class; return $self; } sub get_type { return "inherent"; } sub get_attribute { return shift->{attr_name}; } sub get_trans_to { return shift->{trans_to}; } sub get_trans_from { return shift->{trans_from}; } sub get_autoload_get_list { return [ shift->{get_name} ]; } sub get_autoload_set_list { return [ shift->{set_name} ]; } sub get_data_type { my $self = shift; my $args = shift; my $include_options = 0; if ( ref($args) eq 'HASH' ) { $include_options = $args->{include_options}; } my $table = $self->get_parent()->get_table(); my $column = $table->get_column( $self->{attr_name} ); my $value = $table->get_column_type( $self->{attr_name} ); if ( not defined $value ) { die "Unable to determine datatype of column $self->{attr_name} of type $column->{type}"; } # pass these along $value->{hints} = $self->{hints}; $value->{default} = $self->{default}; # if inclusive options are set we want to return a list of those... if ( $self->{inclusive} and $include_options ) { # copy the manual ones in $value->{options} = [ @{$self->{options}} ]; # check to see if we need to pull anything from the database if ( defined $self->{options_table} and defined $self->{options_column} ) { my $foreign_key = $self->get_parent()->get_table()->get_foreign_key( $self->{attr_name} ); my $value_attr = join '/', $foreign_key->{foreign_table}, $foreign_key->{foreign_column}; my $desc_attr = join '/', $self->{options_table}, $self->{options_column}; my $database = $self->get_parent()->get_database(); my $criteria; if ( $self->{options_criteria} ) { $criteria = $self->{options_criteria}->clone(); } else { $criteria = Xmldoom::Criteria->new(); } my $rs = $database->SearchRS( $criteria, $value_attr, $desc_attr ); $value->{options} = [ ]; while ( $rs->next() ) { my $row = $rs->get_row(); my $val = $row->{$foreign_key->{foreign_column}}; my $desc = $row->{$self->{options_column}}; my $set = 0; # check to see if we manually set this one and then use that one foreach my $manual_opt ( @{$self->{options}} ) { if ( $manual_opt->{value} eq $value ) { $set = 1; } } # add this guy from the database if ( not $set ) { push @{$value->{options}}, { value => $val, description => $desc }; } } } } return $value; } sub get_value_description { my ($self, $value) = @_; # first try the options that we have manually added to property foreach my $opt ( @{$self->{options}} ) { if ( $opt->{value} eq $value ) { return $opt->{description}; } } # second, attempt to pull from a translation table if information to do so # is available. if ( defined $self->{options_table} and defined $self->{options_column} ) { my $database = $self->get_parent()->get_database(); my $table_name = $self->get_parent()->get_table_name(); my $self_attr = join '/', $table_name, $self->{attr_name}; my $desc_attr = join '/', $self->{options_table}, $self->{options_column}; # TODO: should we here use the $self->{options_criteria}. # our criteria is that this properties attribute must equal the given value! my $criteria = Xmldoom::Criteria->new(); $criteria->add_attr( $self_attr, $value ); # grab the value my $rs = $database->SearchRS( $criteria, $desc_attr ); if ( $rs->next() ) { my $row = $rs->get_row(); return $row->{$self->{options_column}}; } } return undef; } sub trans_to { my ($self, $value) = @_; if ( $self->{trans_to} ) { if ( not exists $self->{trans_to}->{$value} ) { die sprintf "Trying to use invalid value '$value' for the '%s' property", $self->get_name(); } $value = $self->{trans_to}->{$value}; } return $value; } sub trans_from { my ($self, $value) = @_; if ( $self->{trans_from} ) { $value = $self->{trans_from}->{$value}; } return $value; } sub get { my ($self, $object) = @_; return $self->trans_from( $object->_get_attr($self->{attr_name}) ); } sub set { my ($self, $object, $value) = @_; $object->_set_attr( $self->{attr_name}, $self->trans_to($value) ); } sub get_query_lval { my $self = shift; my $table_name = $self->{parent}->get_table_name(); my $column_name = $self->{attr_name}; return [ DBIx::Romani::Query::SQL::Column->new( $table_name, $column_name ) ]; } sub get_query_rval { my ($self, $value) = @_; return [ DBIx::Romani::Query::SQL::Literal->new( $self->trans_to($value) ) ]; } sub autoload { my ($self, $object, $func_name, $value) = @_; if ( $func_name eq $self->{set_name} ) { $self->set($object, $value); } elsif ( $func_name eq $self->{get_name} ) { return $self->get($object); } else { die "$func_name is not defined by this property"; } } 1;