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;