--- nfo/perl/libs/Data/Storage/Handler/Tangram.pm 2003/04/19 16:09:48 1.35 +++ nfo/perl/libs/Data/Storage/Handler/Tangram.pm 2003/06/06 11:40:40 1.39 @@ -1,8 +1,25 @@ ############################################ # -# $Id: Tangram.pm,v 1.35 2003/04/19 16:09:48 jonen Exp $ +# $Id: Tangram.pm,v 1.39 2003/06/06 11:40:40 jonen Exp $ # # $Log: Tangram.pm,v $ +# Revision 1.39 2003/06/06 11:40:40 jonen +# fixed bug at 'getFilteredList' +# +# Revision 1.38 2003/05/13 16:38:38 joko +# problems with "tied" on 5.6.1/win32 +# +# Revision 1.37 2003/05/10 17:37:39 jonen +# corrected last commit +# +# Revision 1.36 2003/05/10 17:31:18 jonen +# + added new functions related to 'create' item +# - createNode() +# # creates non-persistent 'deep dummy filled' object +# - insertChildNode() +# # inserts child node at given parent (child node haven't to exists, +# createNode will be injected transparently) +# # Revision 1.35 2003/04/19 16:09:48 jonen # + added operator dispatching (currently for getting ref-type) at 'getListFiltered' # @@ -512,7 +529,9 @@ # TODO: is_op? # dispatch un-common operators if exists if($filter->{op} eq "ref") { - push @tfilters, 'ref($remote->{' . $filter->{key} . '})' . " eq '$filter->{val}'"; + # do nothing, results will be filtered later cause 'tangram-filter' doesn't support 'ref' query + #print "Filter->op eq 'ref'.\n"; + #push @tfilters, 'ref($remote->{' . $filter->{key} . '})' . " eq '$filter->{val}'"; } else { # HACK: build eval-string (sorry) to get filtered list - please give advice here push @tfilters, '$remote->{' . $filter->{key} . '}' . " $filter->{op} '$filter->{val}'"; @@ -538,6 +557,23 @@ @results = eval($evalstring); die $@ if $@; + + # filter results + if($filters->[0]->{op} eq "ref") { + #print "Filter->op eq 'ref'.\n"; + my $att_name = $filters->[0]->{key}; + my $att_val = $filters->[0]->{val}; + my @filtered; + foreach(@results) { + if(ref($_->{$att_name}) eq $att_val) { + push @filtered, $_; + } + } + @results = @filtered; + } + + #print "results: " . Dumper(\@results); + return \@results; } @@ -714,6 +750,16 @@ $self->erase($object); + } elsif ($crud eq 'CREATE') { + + my $nodename = $query->{node}; + my $newnode = $self->createNode($nodename); + my $id = $self->{_COREHANDLE}->insert($newnode); + + print "Saved new node $nodename with GUID $newnode->{guid}, OID '$id': " . Dumper($newnode) . "\n"; + + return $newnode; + } } @@ -868,5 +914,132 @@ $self->{dataStorageLayer}->disconnect(); } + +sub createNode { + my $self = shift; + my $classname = shift; + + my $obj = $classname->new(); + + my $attr_options = Class::Tangram::attribute_options($classname); + #print "Attribute Options: " . Dumper($attr_options); + + my $attr_types = Class::Tangram::attribute_types($classname); + #print "Attribute Types: " . Dumper($attr_types); + + foreach(keys %{$attr_types}) { + if($attr_types->{$_} eq 'string') { + $obj->{$_} = ''; + } elsif($attr_types->{$_} eq 'int') { + $obj->{$_} = 0; + } elsif($attr_types->{$_} eq 'real') { + $obj->{$_} = 0; + } elsif($attr_types->{$_} eq 'rawdatetime') { + $obj->{$_} = '0000-00-00 00:00:00'; + } elsif($attr_types->{$_} eq 'ref') { + if($attr_options->{$_}->{class}) { + $obj->{$_} = $self->createNode($attr_options->{$_}->{class}); + } else { + #$obj->{$_} = undef(); + } + } elsif($attr_types->{$_} eq 'iarray') { + $obj->{$_} = [ ]; + } elsif($attr_types->{$_} eq 'hash') { + $obj->{$_} = { }; + } elsif($attr_types->{$_} eq 'flat_hash') { + $obj->{$_} = { }; + } + } + + #print "New Object: " . Dumper($obj); + + return $obj; +} + + + sub insertChildNode { + my $self = shift; + my $child_entry = shift; + my $query_args = shift; + + my $core = $self->{_COREHANDLE}; + my $nodename = $query_args->{nodename}; + + # get parent object + my $query = { + node => $query_args->{parent}->{nodename}, + options => { GUID => $query_args->{parent}->{guid}, }, + }; + my $cursor = $self->sendQuery($query); + my $parent = $cursor->getNextEntry(); + + # debug + #print "Parent_org: " . Dumper($parent); + + # Create child node object if isn't already done + # ($child_entry have to be the class name then...) + if(!ref($child_entry)) { + $child_entry = $self->createNode($child_entry); + # it could be insert 'manually' or will be insert 'transparent' if parent will be updated + #$core->insert($child_entry); + #print "Create child object [$nodename]: " . Dumper($child_entry); + } + + # get reference of tied node (seems, only on Linux node's are tied!!) + my $tied_node = tied $parent->{$nodename}; + + # insert/change child entry at parent + #print "reference: " . ref($parent->{$nodename}) . "\n"; + if(ref($parent->{$nodename}) eq 'ARRAY') { + # (seems, only on Linux node's are tied!!) + if($tied_node) { + # all tangram types are tied as 'SCALAR' with special 'FETCH', 'STORE' methods per type, + # so a 'PUSH' is not implemented (which could be then done transparently) + my $array = $tied_node->FETCH; + push @$array, $child_entry; + $tied_node->STORE($array); + # node will be normaly untied at 'STORE' + if(tied $parent->{$nodename}) { print "already tied !!\n"; } + else { undef $tied_node; } + } else { + push @{$parent->{$nodename}}, $child_entry; + } + } + elsif(ref($parent->{$nodename}) eq 'HASH') { + if(my $key = $query_args->{hash_key}) { + # (seems, only on Linux node's are tied!!) + if($tied_node) { + # same problem as with 'ARRAY': + # all tangram types are tied as 'SCALAR' with special 'FETCH', 'STORE' methods per type. + my $hash = $tied_node->FETCH; + $hash->{$key} = $child_entry; + $tied_node->STORE($hash); + # node will be normaly untied at 'STORE' + if(tied $parent->{$nodename}) { print "already tied !!\n"; } + else { undef $tied_node; } + } else { + $parent->{$nodename}->{$key} = $child_entry; + } + } else { + print "ERROR: No HASH KEY given, so not able to insert hash entry!"; + } + } + else { + $parent->{$nodename} = $child_entry; + } + + # debug + #print "Parent_new: " . Dumper($parent); + + # save parent + $core->update($parent); + + # debug + #print "Saved Parent: ". Dumper($parent); + + return $child_entry; + } + + 1; __END__