Mercurial > pub > Impl
diff Lib/IMPL/Serialization.pm @ 278:4ddb27ff4a0b
core refactoring
author | cin |
---|---|
date | Mon, 04 Feb 2013 02:10:37 +0400 |
parents | c477f24f1980 |
children | a8dbddf491dd |
line wrap: on
line diff
--- a/Lib/IMPL/Serialization.pm Fri Feb 01 16:37:59 2013 +0400 +++ b/Lib/IMPL/Serialization.pm Mon Feb 04 02:10:37 2013 +0400 @@ -2,313 +2,334 @@ use strict; package IMPL::Serialization::Context; -use parent qw(IMPL::Object); -use IMPL::Class::Property; -use IMPL::Class::Property::Direct; -use IMPL::Exception; +use IMPL::Exception(); use Scalar::Util qw(refaddr); -BEGIN { - private _direct property ObjectWriter => prop_all; - private _direct property Context => prop_all; - private _direct property NextID => prop_all; +use IMPL::Const qw(:prop); +use IMPL::declare { + base => [ 'IMPL::Object' => undef ], + props => [ + _objectWriter => PROP_RW | PROP_DIRECT, + _context => PROP_RW | PROP_DIRECT, + _nextId => PROP_RW | PROP_DIRECT, + serializer => PROP_RW | PROP_DIRECT, + _state => PROP_RW | PROP_DIRECT + ] +}; - public _direct property Serializer => prop_all; - - private _direct property State => prop_all; -} - -sub STATE_CLOSED () { 0 } -sub STATE_OPENED () { 1 } +sub STATE_CLOSED () { 0 } +sub STATE_OPENED () { 1 } sub STATE_COMPLEX () { 2 } -sub STATE_DATA () { 3 } +sub STATE_DATA () { 3 } sub CTOR { - my ($this,%args) = @_; - - $this->{$ObjectWriter} = $args{'ObjectWriter'}; - $this->{$NextID} = 1; - $this->{$Serializer} = ($args{'Serializer'} ? $args{'Serializer'} : \&DefaultSerializer ); - $this->{$State} = STATE_CLOSED; - - return 1; + my ( $this, %args ) = @_; + + $this->{$_objectWriter} = $args{'ObjectWriter'}; + $this->{$_nextId} = 1; + $this->{$serializer} = + ( $args{'Serializer'} ? $args{'Serializer'} : \&DefaultSerializer ); + $this->{$_state} = STATE_CLOSED; + + return 1; } sub AddVar { - my ($this,$sName,$Var) = @_; - - die new Exception ('Invalid operation') if $this->{$State} == STATE_DATA; - - if (not ref $Var) { - my $prevState = $this->{$State}; - - $this->{$ObjectWriter}->BeginObject(name => $sName); - $this->{$State} = STATE_OPENED; - - $this->{$Serializer}->($this,\$Var); - - $this->{$ObjectWriter}->EndObject(); - - if ($prevState == STATE_OPENED) { - $this->{$State} = STATE_COMPLEX; - } else { - $this->{$State} = $prevState; + my ( $this, $sName, $Var ) = @_; + + die new Exception('Invalid operation') if $this->{$_state} == STATE_DATA; + + if ( not ref $Var ) { + my $prevState = $this->{$_state}; + + $this->{$_objectWriter}->BeginObject( name => $sName ); + $this->{$_state} = STATE_OPENED; + + $this->{$serializer}->( $this, \$Var ); + + $this->{$_objectWriter}->EndObject(); + + if ( $prevState == STATE_OPENED ) { + $this->{$_state} = STATE_COMPLEX; + } + else { + $this->{$_state} = $prevState; + } + return 0; } - return 0; - } - - my $PrevState = $this->{$State}; - - my $ObjID = $this->{$Context}->{refaddr $Var}; - if ($ObjID) { - $this->{$ObjectWriter}->BeginObject(name => $sName, refid => $ObjID); - $this->{$ObjectWriter}->EndObject(); + + my $PrevState = $this->{$_state}; + + my $ObjID = $this->{$_context}->{ refaddr $Var}; + if ($ObjID) { + $this->{$_objectWriter}->BeginObject( name => $sName, refid => $ObjID ); + $this->{$_objectWriter}->EndObject(); + return $ObjID; + } + + $ObjID = $this->{$_nextId}; + $this->{$_nextId} = $ObjID + 1; + + $this->{$_context}->{ refaddr $Var} = $ObjID; + + $this->{$_objectWriter} + ->BeginObject( name => $sName, type => ref($Var), id => $ObjID ); + + $this->{$_state} = STATE_OPENED; + $this->{$serializer}->( $this, $Var ); + + $this->{$_objectWriter}->EndObject(); + + if ( $PrevState == STATE_OPENED ) { + $this->{$_state} = STATE_COMPLEX; + } + else { + $this->{$_state} = $PrevState; + } + return $ObjID; - } - - $ObjID = $this->{$NextID}; - $this->{$NextID} = $ObjID + 1; - - $this->{$Context}->{refaddr $Var} = $ObjID; - - $this->{$ObjectWriter}->BeginObject(name => $sName, type => ref($Var), id => $ObjID); - - $this->{$State} = STATE_OPENED; - $this->{$Serializer}->($this,$Var); - - $this->{$ObjectWriter}->EndObject(); - - if ($PrevState == STATE_OPENED) { - $this->{$State} = STATE_COMPLEX; - } else { - $this->{$State} = $PrevState; - } - - return $ObjID; } sub SetData { - my ($this,$Data,$Type) = @_; - - die new Exception ('The object should be a scalar value') if ref $Data; - die new Exception ('Invalid operation') if $this->{$State} != STATE_OPENED; - - $this->{$ObjectWriter}->SetData($Data,$Type); - - $this->{$State} = STATE_DATA; - - return 1; + my ( $this, $data, $type ) = @_; + + die new Exception('The object should be a scalar value') if ref $data; + die new Exception('Invalid operation') if $this->{$_state} != STATE_OPENED; + + $this->{$_objectWriter}->SetData( $data, $type ); + + $this->{$_state} = STATE_DATA; + + return 1; } sub DefaultSerializer { - my ($Context, $refObj) = @_; - - if (ref($refObj) eq 'SCALAR') { - $Context->SetData($$refObj, 'SCALAR'); - } elsif (ref($refObj) eq 'ARRAY') { - $Context->AddVar('item',$_) foreach @$refObj; - } elsif (ref($refObj) eq 'HASH') { - while (my ($key,$value) = each %$refObj) { - $Context->AddVar($key,$value); + my ( $_context, $refObj ) = @_; + + if ( ref($refObj) eq 'SCALAR' ) { + $_context->SetData( $$refObj, 'SCALAR' ); + } + elsif ( ref($refObj) eq 'ARRAY' ) { + $_context->AddVar( 'item', $_ ) foreach @$refObj; + } + elsif ( ref($refObj) eq 'HASH' ) { + while ( my ( $key, $value ) = each %$refObj ) { + $_context->AddVar( $key, $value ); + } } - } elsif (ref($refObj) eq 'REF') { - $Context->AddVar('ref',$$refObj); - } else { - if (ref $refObj and $refObj->UNIVARSAL::can('save')) { - $refObj->save($Context); - } else { - die new Exception('Cant serialize the object of the type: '.ref($refObj)); + elsif ( ref($refObj) eq 'REF' ) { + $_context->AddVar( 'ref', $$refObj ); } - } - - return 1; + else { + if ( ref $refObj and $refObj->UNIVARSAL::can('save') ) { + $refObj->save($_context); + } + else { + die new Exception( + 'Cant serialize the object of the type: ' . ref($refObj) ); + } + } + + return 1; } package IMPL::Deserialization::Context; -use parent qw(IMPL::Object); -use IMPL::Class::Property; -use IMPL::Class::Property::Direct; -use IMPL::Exception; - -BEGIN { - private _direct property Context => prop_all; - - # структура информации об объекте - # { - # Type => 'typename', - # Name => 'object_name', - # Data => $Data, - # Id => 'object_id' - # } - private _direct property CurrentObject => prop_all; +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Exception => 'IMPL::Exception', + Loader => 'IMPL::Code::Loader' + }, + base => [ 'IMPL::Object' => undef ], + props => [ - private _direct property ObjectsPath => prop_all; - - public _direct property Root => prop_get; - - # пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ - # ObjectFactory($Type,$DeserializationData,$refSurogate) - # $Type - пїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ - # $DeserializationData - пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ, - # пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ. - # $refSurogate - пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ. - # пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ undef - private _direct property ObjectFactory => prop_all; - - # пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ. - # SurogateHelper($Type) - # $Type пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ. - private _direct property SurrogateHelper => prop_all; -} + # структура информации об объекте + # { + # Type => 'typename', + # Name => 'object_name', + # Data => $data, + # Id => 'object_id' + # } + _context => PROP_RW | PROP_DIRECT, + _currentObject => PROP_RW | PROP_DIRECT, + _objectsPath => PROP_RW | PROP_DIRECT, + root => PROP_RW | PROP_DIRECT + ] +}; sub CTOR { - my ($this,%args) = @_; - $this->{$CurrentObject} = undef; - $this->{$Root} = undef; - $this->{$ObjectFactory} = $args{ObjectFactory} if $args{ObjectFactory}; - $this->{$SurrogateHelper} = $args{SurrogateHelper} if $args{SurrogateHelper}; + my ( $this, %args ) = @_; + $this->{$_currentObject} = undef; + $this->{$root} = undef; } sub OnObjectBegin { - my ($this,$name,$rhProps) = @_; - - die new Exception("Invalid data from an ObjectReader","An object reader should pass a referense to a hash which contains attributes of an object") if (ref $rhProps ne 'HASH'); - die new Exception("Trying to create second root object") if not $this->{$CurrentObject} and $this->{$Root}; - - if ($rhProps->{'refid'}) { - my $refObj = $this->{$Context}->{$rhProps->{'refid'}}; - die new Exception("A reference to a not existing object found") if not $refObj; - my $rhCurrentObj = $this->{$CurrentObject}; + my ( $this, $name, $rhProps ) = @_; + + die Exception->new( + "Invalid data from an ObjectReader", +"An object reader should pass a referense to a hash which contains attributes of an object" + ) if ( ref $rhProps ne 'HASH' ); + + die Exception->new("Trying to create second root object") + if not $this->{$_currentObject} and $this->{$root}; + + if ( $rhProps->{'refid'} ) { + + my $refObj = $this->{$_context}->{ $rhProps->{'refid'} }; + + die Exception->new("A reference to a not existing object found") + if not $refObj; + + my $rhCurrentObj = $this->{$_currentObject}; + + die Exception->new("The root object can't be a reference") + if not $rhCurrentObj; + + if ( $rhCurrentObj->{'Data'} ) { + + die Exception->new( "Invalid serializaed data", + "Plain deserialization data for an object already exist" ) + if not ref $rhCurrentObj->{'Data'}; - die new Exception("The root object can't be a reference") if not $rhCurrentObj; - - if ($rhCurrentObj->{'Data'}) { - die new Exception("Invalid serializaed data","Plain deserialization data for an object already exist") if not ref $rhCurrentObj->{'Data'}; - push @{$rhCurrentObj->{'Data'}}, $name,$refObj; + push @{ $rhCurrentObj->{'Data'} }, $name, $refObj; + } else { + $rhCurrentObj->{'Data'} = [ $name, $refObj ]; + } + + push @{ $this->{$_objectsPath} }, $rhCurrentObj; + $this->{$_currentObject} = undef; + } else { - $rhCurrentObj->{'Data'} = [$name,$refObj]; + push @{ $this->{$_objectsPath} }, $this->{$_currentObject} + if $this->{$_currentObject}; + + $this->{$_currentObject} = { + Name => $name, + Type => $rhProps->{'type'} || 'SCALAR', + Id => $rhProps->{'id'}, + refId => $rhProps->{'refid'} + }; + + if ( defined $rhProps->{'id'} ) { + die new IMPL::Exception( +"Trying to create a simple object instead of a reference, type is missing.", + $name, $rhProps->{id} + ) unless $rhProps->{'type'}; + + $this->{$_context}->{ $rhProps->{'id'} } = $this->CreateSurrogate( $rhProps->{'type'} ); + } } - # пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ OnObjectEnd пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ. пїЅ.пїЅ. пїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ - push @{$this->{$ObjectsPath}},$rhCurrentObj; - $this->{$CurrentObject} = undef; - - } else { - push @{$this->{$ObjectsPath}},$this->{$CurrentObject} if $this->{$CurrentObject}; - - $this->{$CurrentObject} = { - Name => $name, - Type => $rhProps->{'type'} || 'SCALAR', - Id => $rhProps->{'id'}, - refId => $rhProps->{'refid'} - }; - - if (defined $rhProps->{'id'}) { - die new IMPL::Exception("Trying to create a simple object instead of a reference, type is missing.",$name,$rhProps->{id}) unless $rhProps->{'type'} ; - $this->{$Context}->{$rhProps->{'id'}} = $this->{$SurrogateHelper} ? $this->{$SurrogateHelper}->($rhProps->{'type'}) : DefaultSurrogateHelper($rhProps->{'type'}); - } - } - - return 1; + return 1; } sub OnObjectData { - my ($this,$data) = @_; - - my $rhObject = $this->{$CurrentObject}; - - die new Exception("Trying to set data for an object which not exists") if not $rhObject; - - die new Exception("Deserialization data already exists for a current object", "ObjectName= $rhObject->{'Name'}") if $rhObject->{'Data'}; - - $rhObject->{'Data'} = $data; - - return 1; + my ( $this, $data ) = @_; + + my $rhObject = $this->{$_currentObject}; + + die Exception->new("Trying to set data for an object which not exists") + if not $rhObject; + + die Exception->new( + "Deserialization data already exists for a current object", + "ObjectName= $rhObject->{'Name'}" ) + if $rhObject->{'Data'}; + + $rhObject->{'Data'} = $data; + + return 1; } { - my $AutoId = 0; - sub OnObjectEnd { - my ($this,$name) = @_; - - my $rhObject = $this->{$CurrentObject}; - my $rhPrevObject = pop @{$this->{$ObjectsPath}}; - - # пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ - пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ - пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ - # пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ - if ((not defined($rhObject)) && $rhPrevObject) { - $this->{$CurrentObject} = $rhPrevObject; - return 1; + my $autoId = 0; + + sub OnObjectEnd { + my ( $this, $name ) = @_; + + my $rhObject = $this->{$_currentObject}; + my $rhPrevObject = pop @{ $this->{$_objectsPath} }; + + if ( ( not defined($rhObject) ) && $rhPrevObject ) { + $this->{$_currentObject} = $rhPrevObject; + return 1; + } + + my $refObj = $this->CreateObject( + $rhObject->{'Type'}, + $rhObject->{'Data'}, + $rhObject->{'Id'} + ? $this->{$_context}->{ $rhObject->{'Id'} } + : undef + ); + + die Exception->new("Trying to close a non existing oject") + if not $rhObject; + + my $data; + + if ( $rhObject->{'Id'} ) { + $this->{$_context}->{ $rhObject->{'Id'} } = $refObj; + $data = $refObj; + } + else { + if ( ref $refObj ne 'SCALAR' ) { + $rhObject->{Id} = "auto$autoId"; + $autoId++; + $this->{$_context}->{ $rhObject->{'Id'} } = $refObj; + $data = $refObj; + } + else { + $data = ${$refObj}; + } + } + + if ( not $rhPrevObject ) { + $this->{$root} = $data; + } + else { + if ( $rhPrevObject->{'Data'} ) { + die Exception->new( + "Trying append a reference to an object to the plain data") + if not ref $rhPrevObject->{'Data'}; + + push @{ $rhPrevObject->{'Data'} }, $rhObject->{'Name'}, $data; + } + else { + $rhPrevObject->{'Data'} = [ $rhObject->{'Name'}, $data ]; + } + } + + $this->{$_currentObject} = $rhPrevObject; + + return 1; } - - my $refObj = $this->{$ObjectFactory} ?$this->{$ObjectFactory}->($rhObject->{'Type'},$rhObject->{'Data'},$rhObject->{'Id'} ? $this->{$Context}->{$rhObject->{'Id'}} : undef) : DefaultFactory($rhObject->{'Type'},$rhObject->{'Data'},$rhObject->{'Id'} ? $this->{$Context}->{$rhObject->{'Id'}} : undef); - - die new Exception("Trying to close a non existing oject") if not $rhObject; - - my $Data; - - if ($rhObject->{'Id'}) { - $this->{$Context}->{$rhObject->{'Id'}} = $refObj; - $Data = $refObj; - } else { - if (ref $refObj ne 'SCALAR') { - $rhObject->{Id} = "auto$AutoId"; - $AutoId ++; - $this->{$Context}->{$rhObject->{'Id'}} = $refObj; - $Data = $refObj; - } else { - $Data = ${$refObj}; - } - } - - if (not $rhPrevObject) { - $this->{$Root} = $Data; - } else { - if ($rhPrevObject->{'Data'}) { - die new Exception("Trying append a reference to an object to the plain data") if not ref $rhPrevObject->{'Data'}; - push @{$rhPrevObject->{'Data'}},$rhObject->{'Name'},$Data; - } else { - $rhPrevObject->{'Data'} = [$rhObject->{'Name'},$Data]; - } - } - - $this->{$CurrentObject} = $rhPrevObject; - - return 1; - } } -{ - my %classes; - sub _load_class { - return if $classes{$_[0]}; - - die new IMPL::Exception("Invalid class name",$_[0]) unless $_[0] =~ m/^(\w+(?:\:\:\w+)*)$/; - - eval "require $1"; - $classes{$_[0]} = 1; - } -} +sub CreateSurrogate { + my ($this,$type) = @_; -sub DefaultSurrogateHelper { - my ($Type) = @_; - - if ($Type eq 'SCALAR' or $Type eq 'REF') { - my $var; - return \$var; - } elsif ($Type eq 'ARRAY') { - return []; - } elsif ($Type eq 'HASH') { - return {}; - } elsif ($Type) { - _load_class($Type); - if (UNIVERSAL::can($Type,'surrogate')) { - return $Type->surrogate(); - } else { - return bless {}, $Type; + if ( $type eq 'SCALAR' or $type eq 'REF' ) { + my $var; + return \$var; + } + elsif ( $type eq 'ARRAY' ) { + return []; + } + elsif ( $type eq 'HASH' ) { + return {}; } - } + elsif ($type) { + Loader->safe->Require($type); + if ( eval { $type->can('surrogate') } ) { + return $type->surrogate(); + } + else { + return bless {}, $type; + } + } } # deserialization context: @@ -317,90 +338,112 @@ # .... # ] -sub DefaultFactory { - my ($Type,$Data,$refSurogate) = @_; - - if ($Type eq 'SCALAR') { - die new Exception("SCALAR needs a plain data for a deserialization") if ref $Data; - if ($refSurogate) { - $$refSurogate = $Data; - return $refSurogate; - } else { - return \$Data; +sub CreateObject { + my ($this, $type, $data, $refSurogate ) = @_; + + if ( $type eq 'SCALAR' ) { + die Exception->new("SCALAR needs a plain data for a deserialization") + if ref $data; + if ($refSurogate) { + $$refSurogate = $data; + return $refSurogate; + } + else { + return \$data; + } } - } elsif ($Type eq 'ARRAY') { - $Data ||= []; - die new Exception("Invalid a deserialization context when deserializing ARRAY") if not ref $Data and defined $Data; - if (not ref $refSurogate) { - my @Array; - $refSurogate = \@Array; - } - for (my $i = 0; $i < scalar(@{$Data})/2; $i++) { - push @$refSurogate,$Data->[$i*2+1]; + elsif ( $type eq 'ARRAY' ) { + $data ||= []; + die Exception->new( + "Invalid a deserialization context when deserializing ARRAY") + if not ref $data and defined $data; + if ( not ref $refSurogate ) { + my @Array; + $refSurogate = \@Array; + } + for ( my $i = 0 ; $i < scalar( @{$data} ) / 2 ; $i++ ) { + push @$refSurogate, $data->[ $i * 2 + 1 ]; + } + return $refSurogate; } - return $refSurogate; - } elsif ($Type eq 'HASH') { - $Data ||= []; - die new Exception("Invalid a deserialization context when deserializing HASH") if not ref $Data and defined $Data; - if (not ref $refSurogate) { - $refSurogate = {}; - } - for (my $i = 0; $i< @$Data; $i+= 2) { - $refSurogate->{$Data->[$i]} = $Data->[$i+1]; + elsif ( $type eq 'HASH' ) { + $data ||= []; + die Exception->new( + "Invalid a deserialization context when deserializing HASH") + if not ref $data and defined $data; + if ( not ref $refSurogate ) { + $refSurogate = {}; + } + for ( my $i = 0 ; $i < @$data ; $i += 2 ) { + $refSurogate->{ $data->[$i] } = $data->[ $i + 1 ]; + } + return $refSurogate; } - return $refSurogate; - } elsif ($Type eq 'REF') { - $Data ||= []; - die new Exception("Invalid a deserialization context when deserializing REF") if not ref $Data and defined $Data; - if (not ref $refSurogate) { - my $ref = $Data->[1]; - return \$ref; - } else { - $$refSurogate = $Data->[1]; - return $refSurogate; + elsif ( $type eq 'REF' ) { + $data ||= []; + die Exception->new( + "Invalid a deserialization context when deserializing REF") + if not ref $data and defined $data; + if ( not ref $refSurogate ) { + my $ref = $data->[1]; + return \$ref; + } + else { + $$refSurogate = $data->[1]; + return $refSurogate; + } } - } else { - _load_class($Type); - if ( $Type->UNIVERSAL::can('restore') ) { - return $Type->restore($Data,$refSurogate); - } else { - die new Exception("Don't know how to deserialize $Type"); + else { + Loader->safe->Require($type); + if ( eval { $type->can('restore') } ) { + return $type->restore( $data, $refSurogate ); + } + else { + die Exception->new("Don't know how to deserialize $type"); + } } - } } package IMPL::Serializer; -use parent qw(IMPL::Object); -use IMPL::Class::Property; -use IMPL::Class::Property::Direct; -use IMPL::Exception; - -BEGIN { - private _direct property Formatter => prop_all; -} +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Exception => 'IMPL::Exception', + SerializationContext => '-IMPL::Serialization::Context', + DeserializationContext => '-IMPL::Deserialization::Context' + }, + base => [ + 'IMPL::Object' => undef + ], + props => [ + _formatter => PROP_RW + ] +}; sub CTOR { - my ($this,%args) = @_; - $this->Formatter($args{'Formatter'}) or die new Exception("Omitted mandatory parameter 'Formatter'"); + my ( $this, %args ) = @_; + $this->_formatter( $args{formatter} ) + or die Exception->new("Omitted mandatory parameter 'formatter'"); } sub Serialize { - my $this = shift; - my ($hStream,$Object) = @_; - my $ObjWriter = $this->Formatter()->CreateWriter($hStream); - my $Context = new IMPL::Serialization::Context(ObjectWriter => $ObjWriter); - $Context->AddVar('root',$Object); - return 1; + my $this = shift; + my ( $hStream, $Object ) = @_; + my $ObjWriter = $this->_formatter->CreateWriter($hStream); + my $context = + SerializationContext->new( objectWriter => $ObjWriter ); + $context->AddVar( 'root', $Object ); + return 1; } sub Deserialize { - my $this = shift; - my ($hStream) = @_; - my $Context = new IMPL::Deserialization::Context(); - my $ObjReader = $this->Formatter()->CreateReader($hStream,$Context); - $ObjReader->Parse(); - return $Context->Root(); + my $this = shift; + my ($hStream) = @_; + my $context = DeserializationContext->new(); + my $ObjReader = $this->_formatter->CreateReader( $hStream, $context ); + $ObjReader->Parse(); + return $context->root; } 1;