X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FStorage%2FEngine.pm;h=ec96c707c7a318aa94ad37aaf8b37fcfd00f7ec9;hb=45d9a73cb319d9cd4d3e30d07526d72cb3e11ad2;hp=7f3bbb4cce6e6252fd24feda7bfe2c99bffa61f3;hpb=ba5bba75ba0c4f8af075e95ce3b00e5376bedf5c;p=gitmo%2FMooseX-Storage.git diff --git a/lib/MooseX/Storage/Engine.pm b/lib/MooseX/Storage/Engine.pm index 7f3bbb4..ec96c70 100644 --- a/lib/MooseX/Storage/Engine.pm +++ b/lib/MooseX/Storage/Engine.pm @@ -2,14 +2,20 @@ package MooseX::Storage::Engine; use Moose; -our $VERSION = '0.01'; +our $VERSION = '0.02'; # the class marker when # serializing an object. our $CLASS_MARKER = '__CLASS__'; has 'storage' => ( - is => 'rw', + is => 'ro', + isa => 'HashRef', + default => sub {{}} +); + +has 'seen' => ( + is => 'ro', isa => 'HashRef', default => sub {{}} ); @@ -21,6 +27,11 @@ has 'class' => (is => 'rw', isa => 'Str'); sub collapse_object { my $self = shift; + + # NOTE: + # mark the root object as seen ... + $self->seen->{$self->object} = undef; + $self->map_attributes('collapse_attribute'); $self->storage->{$CLASS_MARKER} = $self->object->meta->name; return $self->storage; @@ -28,6 +39,11 @@ sub collapse_object { sub expand_object { my ($self, $data) = @_; + + # NOTE: + # mark the root object as seen ... + $self->seen->{$data} = undef; + $self->map_attributes('expand_attribute', $data); return $self->storage; } @@ -47,6 +63,14 @@ sub expand_attribute { sub collapse_attribute_value { my ($self, $attr) = @_; my $value = $attr->get_value($self->object); + + # NOTE: + # this might not be enough, we might + # need to make it possible for the + # cycle checker to return the value + $self->check_for_cycle_in_collapse($attr, $value) + if ref $value; + if (defined $value && $attr->has_type_constraint) { my $type_converter = $self->find_type_handler($attr->type_constraint); (defined $type_converter) @@ -58,6 +82,12 @@ sub collapse_attribute_value { sub expand_attribute_value { my ($self, $attr, $value) = @_; + + # NOTE: + # (see comment in method above ^^) + $self->check_for_cycle_in_expansion($attr, $value) + if ref $value; + if (defined $value && $attr->has_type_constraint) { my $type_converter = $self->find_type_handler($attr->type_constraint); $value = $type_converter->{expand}->($value); @@ -65,12 +95,40 @@ sub expand_attribute_value { return $value; } +# NOTE: +# possibly these two methods will +# be used by a cycle supporting +# engine. However, I am not sure +# if I can make a cycle one work +# anyway. + +sub check_for_cycle_in_collapse { + my ($self, $attr, $value) = @_; + (!exists $self->seen->{$value}) + || confess "Basic Engine does not support cycles in class(" + . ($attr->associated_metaclass->name) . ").attr(" + . ($attr->name) . ") with $value"; + $self->seen->{$value} = undef; +} + +sub check_for_cycle_in_expansion { + my ($self, $attr, $value) = @_; + (!exists $self->seen->{$value}) + || confess "Basic Engine does not support cycles in class(" + . ($attr->associated_metaclass->name) . ").attr(" + . ($attr->name) . ") with $value"; + $self->seen->{$value} = undef; +} + # util methods ... sub map_attributes { my ($self, $method_name, @args) = @_; map { $self->$method_name($_, @args) + } grep { + # Skip our special skip attribute :) + !$_->isa('MooseX::Storage::Meta::Attribute::DoNotSerialize') } ($self->object || $self->class)->meta->compute_all_applicable_attributes; } @@ -170,7 +228,7 @@ my %TYPES = ( #'CodeRef' => { # expand => sub {}, # use eval ... # collapse => sub {}, # use B::Deparse ... - #} + #} ); sub add_custom_type_handler { @@ -233,12 +291,12 @@ __END__ =head1 NAME -MooseX::Storage::Engine - -=head1 SYNOPSIS +MooseX::Storage::Engine - The meta-engine to handle collapsing and expanding objects =head1 DESCRIPTION +No user serviceable parts inside. If you really want to know, read the source :) + =head1 METHODS =head2 Accessors @@ -251,6 +309,8 @@ MooseX::Storage::Engine =item B +=item B + =back =head2 API @@ -275,6 +335,10 @@ MooseX::Storage::Engine =item B +=item B + +=item B + =item B =back