#!/usr/local/bin/perl package Text::PORE::Object; use Exporter; @Text::PORE::Object::ISA = qw(Exporter); $Text::PORE::Object::VERSION = "0.05"; sub new { my ($type) = shift; my (%att_list) = @_; my ($self) = {}; foreach $key (keys %att_list) { $self->{"\L$key\E"} = $att_list{$key}; } bless $self; $self; } ####################################### # getAttribute($name) ####################################### sub getAttribute() { return GetAttribute(@_); }; ####################################### # setAttribute($name=>$value) ####################################### sub setAttribute() { LoadAttributes(@_); } ####################################### # setAttributes($name1=>$value1, $name2=>$value2, ..., $nameN=>$valueN) ####################################### sub setAttributes() { LoadAttributes(@_); } sub GetClassType { my($type) = shift; my($dummy); ($type,$dummy) = split(/\=/,$type); return ($type); } ####################################### # Given the attribute name, # return the value of itself, closest ancestor or default ####################################### sub GetAttribute { my ($self) = shift; my ($att) = @_; $att = "\L$att\E"; return ($self->{$att}) if (defined $self->{$att}); my ($obj_id); if ($obj_id = $self->{"ID\_$att"}) { ##################################### # this attribute exists, but the object is now allocated yet # allocate the object now ##################################### my($class) = $::obj_type_2_class{$self->{"TYPE_$att"}}; if ($class) { require "$class.pm"; import $class; if ($::_PRINT_NEW_) { print "new $class(id=>$obj_id)\n"; } $self->{$att} = $class->new (id=>$obj_id); } return ($self->{$att}); } elsif ($self->{'parent'}) { ##################################### # this attribute dosn't exists, # look one level up ##################################### return ($self->{'parent'}->GetAttribute($att)); } else { ######################################### # this attribute is not found anywhere within myself and # my ancestors, return the default one ######################################### #print "default:[$att]=[$::default_attribs{$att}]"; return ($::default_attribs{$att}); } } ###################################### # returns a reference to a list of all attribute names ###################################### sub GetAllAttributeNames { my($self) = shift; my ($att,@att_list); $self->FinalizeAllAttributes; foreach $att (sort keys %{$self}) { if ($att =~ /^ID_|^TYPE_/) { next; } push (@att_list, $att); } return (\@att_list); } ###################################### # Finalize All the Attributes # Internal Function, outsiders should not care about it. ###################################### sub FinalizeAllAttributes { my($self) = shift; my ($att,$class,$obj_id); foreach $att(keys %{$self}) { if ($att =~ /^ID_(.+)$/) { $obj_id = $self->{$att}; $att = $1; $class = $::obj_type_2_class{$self->{"TYPE_$att"}}; if ($class) { require "$class.pm"; import $class; if ($::_PRINT_NEW_) { print "new $class(id=>$obj_id)\n"; } $self->{$att} = $class->new (id=>$obj_id); } $self->{"ID_$att"} = $self->{"TYPE_$att"} = undef; } } } ###################################### # returns a reference to a hash # the hash keys are the attribute names # the hash values are the attribute values # an example: # $page = new Page(id=>$id); # $hash_ref = $page->GetAllAttributes; # foreach $attr (keys %$hash_ref) { # print "name: $attr, value: $hash_ref->{$attr}"; # .... ###################################### sub GetAllAttributes { my($self) = shift; my ($att,%obj); $self->FinalizeAllAttributes; foreach $att (sort keys %{$self}) { if ($att =~ /^ID_|^TYPE_/) { next; } else { $obj{$att} = $self->{$att}; } } return (\%obj); } ###################################### # Print All Attributes and Values for debugging purpose ###################################### sub PrintAllAttributes { my($self) = shift; my $att_ref = $self->GetAllAttributes; my ($attr,$val); while (($attr,$val) = (each %{$att_ref})) { print "'$attr'=["; if (ref $val eq 'ARRAY') { ### multi-value attribute print "multi: @$val"; } else { print $val; } print "]
\n"; } } ###################################### # Return 1 if these multi-value attribute # $attr has value $value # Return 0 otherwise ###################################### sub MultiValAttrHas { my($self) = shift; my($attr,$val) = @_; if (ref $self->{$attr} ne 'ARRAY') { return 0; } foreach (@{$self->{$attr}}) { if ($_ eq $val) { return 1; } } return 0; } ################################################# # Load Attributes # In: pair(s) of attribute_name and attribute_value # Example: # $object->LoadAttributes($name1=>$value1,$name2=>$value2,...); ################################################# sub LoadAttributes { my($self) = shift; my(%att_list) = @_; foreach $key (keys %att_list) { $self->{"\L$key\E"} = $att_list{$key}; } return $self; } ############################################### # given an attribute name, an id and a type, # create a object, which is my child # if id is 0, then the object is a scalar, use # type as its value ############################################### sub MakeChild { my $self = shift; my($child_name, $id, $type) = @_; ############################################### # it's not a object but a value, return value($type) ############################################### if (!$id) { $self->{$child_name} = $type; } ############################################### # it's a object ############################################### my $class = $::obj_type_2_class{$type}; if ($class) { require "$class.pm"; import $class; if ($::_PRINT_NEW_) { print "new $class(id=>$obj_id)\n"; } my $obj = $class->new(id=>$id,parent=>$self); $self->{$child_name} = $obj; } else { return undef; } } ############################################### # Atts2QueryString # convert attributes to QueryString ############################################### sub Atts2QueryString { my $self = shift; my %atts = @_; $self->LoadAttributes(%atts); my $string = undef; my $key; my $value; foreach $key (keys %{$self}) { if ($key eq 'parent') { next; } $value = urlencode ($self->{$key}); $key = urlencode_word ($key); $string .= "$key=$value\&"; } return $string; } 1; __END__ =head1 NAME Text::PORE::Object - PORE Objects =head1 SYNOPSIS $obj = new Text::PORE::Object('name'=>'Joe Smith'); @chilren = ( new Text::PORE::Object('name'=>'John Smith', 'age'=>10, 'gender'=>'M'), new Text::PORE::Object('name'=>'Jack Smith', 'age'=>15, 'gender'=>'M'), new Text::PORE::Object('name'=>'Joan Smith', 'age'=>20, 'gender'=>'F'), new Text::PORE::Object('name'=>'Jim Smith', 'age'=>25, 'gender'=>'M'), ); $obj->{'children'} = \@chilren; =head1 DESCRIPTION PORE::Object is the superclass of all renderable objects. That is, if you want to render an object, the object must be an instance of PORE::Object or an instance of its subclass. The purpose of this class is to provide methods to create and access attributes. Attributes can be created via the constructor C and setters C and C. Attributes can be retrieve via the getter C. =head1 METHODS =over 4 =item new Usage: new Text::PORE::Object(); new Text::PORE::Object($name1=>$value1, $name2=>$value2, ..., $nameN=>$valueN); The constructor can take no argument or a list of name-value pairs. If a list of name-value pairs is provided, the object is created with the given attributes. =item getAttribute() Usage: $obj->getAttribute($name); This method retrieves the value of the given attribute. If the attribute is an object, its reference is returned. =item setAttribute() Usage: $obj->setAttribute($name=>$value); This method takes a name-value pair. It sets the attribute for the given name to the given value. If the attribute previously has an old value, the new value overrides the old one. =item setAttributes() Usage: $obj->setAttributes($name1=>$value1, $name2=>$value2, ..., $nameN=>$valueN); This method takes a list of name-value pairs. It sets the attribute for each given name to its corresponding value. If the attribute previously has an old value, the new value overrides the old one. =back =head1 AUTHOR Zhengrong Tang, ztang@cpan.org =head1 COPYRIGHT Copyright 2004 by Zhengrong Tang This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut