enclosed is set of object tree helpers
they do conversion via a standard perl hash with input/output available
via yaml and json
there are a few issues with this development only code - its not ready for
production at all
a- methods are stored in a hash via a string conversion facilitated by
sprintf . this was the only way to encode bigint and timestamp into yaml
documents ( without the forced string conversion, they appeared as objects
of their respective classes ). the problem occurs on the re-instantiation
of these objects -- bigint objects return correctly, but the timestamp
objects do not. this is likely because the timestamps are saved in
db-specific formats by rose.
b- the mapping types to hash/array are figured out by reading the ref of
the relationships. this is exceedingly messy, but i couldn't find any
other way to tell the mapping type
c- when rebuilding the rows on tiered objects, the code will set the db
to be that of the top (parent) tiered object. this seems to work right as
I've coded it, but I fear there is something really wrong with this
approach.
also note:
a- the object class is stored in '..xrdbopriv_class' -- '..' was used as
the delimited instead of the '__' that rose uses, because '__' is a valid
column prefix in most dbs , and I didn't want to interfere.
If anyone has time to look through the code and provide feedback or fix
any glaring mistakes, I'd be grateful.
I ended up not needing to use this functionality right now, as Jon
Siracusa made the strip() helper method and I've been happy with that.
but its a pretty useful feature ( IMHO ) if it starts to work right.
use strict;
package P_2XLP::RoseDB_Helpers;
use Rose::DB::Object::Helpers ();
use base qw(Rose::DB::Object::Helpers);
use YAML::Syck ();
use JSON::Syck ();
sub object_tree_as_yaml {
my ( $self )= @_;
local $self->{Rose::DB::Object::Constants::STATE_SAVING()} = 1;
return YAML::Syck::Dump(scalar P_2XLP::RoseDB_Helpers::object_tree_as_hash($self));
}
sub object_tree_from_yaml {
my ( $self , $yaml )= @_;
my $hash= YAML::Syck::Load($yaml);
local $self->{Rose::DB::Object::Constants::STATE_SAVING()} = 1;
return $self->object_tree_from_hashref( $hash );
}
sub object_tree_as_json {
my ( $self )= @_;
local $self->{Rose::DB::Object::Constants::STATE_SAVING()} = 1;
return JSON::Syck::Dump(scalar P_2XLP::RoseDB_Helpers::object_tree_as_hash($self));
}
sub object_tree_from_json {
my ( $self , $json )= @_;
my $hash= JSON::Syck::Load($json);
local $self->{Rose::DB::Object::Constants::STATE_SAVING()} = 1;
return $self->object_tree_from_hashref( $hash );
}
sub object_tree_as_hash {
my ($self)= shift;
my %hash;
my $methods= $self->meta->column_accessor_method_names_hash;
while(my($column, $method) = each(%$methods))
{
$hash{$column}= sprintf "%s" , $self->$method();
}
my %seen_rels;
foreach my $rel ($self->meta->foreign_keys)
{
my $rel_name= $rel->name;
next if $seen_rels{ $rel_name };
if ( my $obj= $rel->object_has_foreign_object($self) )
{
$hash{ $rel_name }= P_2XLP::RoseDB_Helpers::object_tree_as_hash( $obj );
$seen_rels{ $rel_name }= 1;
}
}
foreach my $rel ($self->meta->relationships)
{
my $rel_name= $rel->name;
next if $seen_rels{ $rel_name };
if ( my $objs= $rel->object_has_related_objects($self) )
{
my $mapping_type= ref( $rel );
if (
( $mapping_type eq 'Rose::DB::Object::Metadata::Relationship::ManyToMany' )
||
( $mapping_type eq 'Rose::DB::Object::Metadata::Relationship::OneToMany' )
)
{
my @objs;
foreach my $obj ( @$objs )
{
push @objs, P_2XLP::RoseDB_Helpers::object_tree_as_hash( $obj );
}
$hash{ $rel_name }= [EMAIL PROTECTED];
$seen_rels{ $rel_name }= 1;
}
elsif (
( $mapping_type eq 'Rose::DB::Object::Metadata::Relationship::ManyToOne' )
||
( $mapping_type eq 'Rose::DB::Object::Metadata::Relationship::OneToOne' )
)
{
$hash{ $rel_name }= P_2XLP::RoseDB_Helpers::object_tree_as_hash( $$objs[0] );
$seen_rels{ $rel_name }= 1;
}
}
}
$hash{'..xrdbopriv_class'}= ref( $self );
return \%hash;
}
sub object_tree_from_hashref {
my ( $self , $hash_ref , $parent_object_ref )= @_;
unless ( ref( $self ) eq $hash_ref->{'..xrdbopriv_class'} )
{
#if ( !ref($self) )
#{
# $self= {};
# bless $self , $hash_ref->{'..xrdbopriv_class'};
#}
#else
#{
die sprintf "Wrong class ! Expected '%s' , Received '%s' " , ref($self) , $hash_ref->{'..xrdbopriv_class'} ;
#}
}
local $self->{Rose::DB::Object::Constants::STATE_LOADING()} = 1;
if ( !defined $parent_object_ref )
{
$parent_object_ref= $self;
}
# rebuild the columns
my $methods= $self->meta->column_accessor_method_names_hash;
while(my($column, $method) = each(%$methods))
{
next unless defined $hash_ref->{$column};
$self->$method( $hash_ref->{$column} );
}
# rebuild the subobjects
my %seen_rels;
# the foreign_keys
foreach my $rel ($self->meta->foreign_keys)
{
my $rel_name= $rel->name ;
next if $seen_rels{ $rel_name };
next unless defined $hash_ref->{$rel_name};
$self->$rel_name( $hash_ref->{$rel_name} );
$seen_rels{ $rel_name }= 1;
}
# the relationships
foreach my $rel ($self->meta->relationships)
{
my $rel_name= $rel->name ;
next unless defined $hash_ref->{$rel_name};
next if $seen_rels{ $rel_name };
my $rel_class= $rel->class ;
if ( ref ( $hash_ref->{$rel_name} ) eq 'ARRAY' )
{
my @objs;
foreach my $row ( @{$hash_ref->{$rel_name}} )
{
my $rel_obj= $rel_class->new();
$rel_obj->db( $parent_object_ref->db );
push @objs , P_2XLP::RoseDB_Helpers::object_tree_from_hashref( $rel_obj , $row , $parent_object_ref );
}
$self->$rel_name( [EMAIL PROTECTED] );
}
elsif ( ref ( $hash_ref->{$rel_name} ) eq 'HASH' )
{
my $rel_obj= $rel_class->new();
$rel_obj->db( $parent_object_ref->db );
my $sub_obj= P_2XLP::RoseDB_Helpers::object_tree_from_hashref( $rel_obj , $hash_ref->{$rel_name} , $parent_object_ref );
$self->$rel_name( $sub_obj );
}
else
{
die "wtf?";
}
$seen_rels{ $rel_name }= 1;
}
return $self;
}
1;
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object