# HG changeset patch # User cin # Date 1443086370 -10800 # Node ID af8d359ee4ccdac3fce8917361c7926a34a7db27 # Parent 30e8c6a749370c8cecba89a654cfaff43a42c26a working on di container diff -r 30e8c6a74937 -r af8d359ee4cc lib/IMPL/Config/Bag.pm --- a/lib/IMPL/Config/Bag.pm Mon Sep 21 19:54:10 2015 +0300 +++ b/lib/IMPL/Config/Bag.pm Thu Sep 24 12:19:30 2015 +0300 @@ -2,15 +2,103 @@ use strict; use IMPL::declare { - + base => [ + 'IMPL::Object' => undef + ], + props => [ + parent => '*r', + _cache => '*rw', + _entries => '*rw' + ] }; +sub CTOR { + my ($this, $p) = @_; + + $this->{$parent} = $p; + $this->{$_cache} = {}; + $this->{$_entries} = []; +} + sub Resolve { + my ($this,$role) = @_; + + my $d = $this->GetDescriptor(); +} + +sub GetDescriptor { + my ($this, $role) = @_; + + my $d = $this->{$_cache}{$role}; + return $d if $d and $d->{valid}; + + my @entries = @{$this->{$_entries}}; + + if(my $t = $this->{$parent} && $this->{$parent}->GetDescriptor($role)) { + push @entries, $t; + } + + my $level; + foreach my $entry (@entries) { + my $t = $entry->{isa}{$role}; + next unless defined $t; + if (defined($level) && $level > $t) { + $d = $entry; + $level = $t; + } + } + + if ($d and $d->{valid}) { + $this->{$_cache}{$role} = $d; + return $d; + } else { + return; + } +} + +sub ResolveAll { + my ($this, $role) = @_; + + my $result = $this->{$parent} ? $this->{$parent}->ResolveAll() : []; + + push @$result, map $_->{value}, grep $_->{isa}{$role}, @{$this->{$_entries}}; + + return $result; +} + +sub Register { + my ($this, $role, $isa, $value) = @_; +} + +sub _UpdateDescriptor { } -sub Register { - +package IMPL::Config::Bag::Entry; +use IMPL::Exception(); +use IMPL::declare { + base => [ + 'IMPL::Object::Fields' => undef + ] +}; + +my @fields = qw(owner type isa valid value index); +use fields @fields; + +sub CTOR { + my SELF $this = shift; + my $args = shift; + + $this->{valid} = 1; + $this->{owner} = $args->{owner} or die IMPL::InvalidArgumentException->new("owner"); + $this->{value} = $args->{value} if exists $args->{value}; + $this->{isa} = $args->{isa} if $args->{isa}; +} + +sub Invalidate { + my SELF $this = shift; + + $this->{owner}->_UpdateDescriptor($this); } 1; \ No newline at end of file diff -r 30e8c6a74937 -r af8d359ee4cc lib/IMPL/Config/Container.pm --- a/lib/IMPL/Config/Container.pm Mon Sep 21 19:54:10 2015 +0300 +++ b/lib/IMPL/Config/Container.pm Thu Sep 24 12:19:30 2015 +0300 @@ -1,39 +1,94 @@ package IMPL::Config::Container; use strict; +use IMPL::Exception(); use IMPL::lang qw(:base); use IMPL::declare { require => { - Descriptor => 'IMPL::Config::Descriptor' + Descriptor => 'IMPL::Config::Descriptor', + ValueDescriptor => 'IMPL::Config::ValueDescriptor', + ActivationContext => 'IMPL::Config::ActivationContext', + Hierarchy => 'IMPL::Config::Hierarchy', + Bag => 'IMPL::Config::Bag' }, base => [ 'IMPL::Object' => undef ], props => [ - roles => 'r', - services => 'r', - instances => 'r' + roles => 'r', + services => 'r', + instances => 'r', + parent => 'r' ] }; my $nextRoleId = 1; -use IMPL::Exception(); +sub CTOR { + my ( $this, $parent ) = @_; + + $this->instances( {} ); + + if ($parent) { + $this->roles( Hierarchy->new( $parent->roles ) ); + $this->services( Bag->new( $parent->services ) ); + $this->parent($parent); + } + else { + $this->roles( Hierarchy->new() ); + $this->services( Bag->new() ); + } +} sub Register { - my ($this, $role, $service) = @_; - - die IMPL::InvalidArgumentException->new(role => 'The argument is required') unless $role; - die IMPL::InvalidArgumentException->new('service') unless is($service, Descriptor); - - if (isarray($role)) { - my $tempRole = "unnamed-" . $nextRoleId++; - $this->role->AddRole($tempRole, $role); - $role = $tempRole; + my ( $this, $role, $service ) = @_; + + die IMPL::InvalidArgumentException->new( + role => 'The argument is required' ) + unless $role; + die IMPL::InvalidArgumentException->new('service') + unless is( $service, Descriptor ); + + if ( isarray($role) ) { + my $tempRole = "unnamed-" . $nextRoleId++; + $this->role->AddRole( $tempRole, $role ); + $role = $tempRole; } - - $this->services->Register($role, $service); - + + $service = ValueDescriptor->new( value => $service ) + unless is( $service, Descriptor ); + + $this->services->Register( $role, $this->roles->GetLinearRoleHash($role), $service ); +} + +sub Resolve { + my ( $this, $role, %opts ) = @_; + + my $descriptor = $this->services->Resolve($role); + + return $descriptor->Activate( ActivationContext->new($this) ) + if $descirptor; + + return $opts{default} if exists $opts{default}; +} + +sub ResolveAll { + my ( $this, $role, %opts ) = @_; + + my $all = $this->services->ResolveAll($role); + + my $context; + + my @result; + + foreach my $service (@$all) { + $context = ActivationContext->new($this) + unless $context || $opts{shared}; + + push @result, $service->Activate($context); + } + + return \@result; } 1; diff -r 30e8c6a74937 -r af8d359ee4cc lib/IMPL/Config/Descriptor.pm --- a/lib/IMPL/Config/Descriptor.pm Mon Sep 21 19:54:10 2015 +0300 +++ b/lib/IMPL/Config/Descriptor.pm Thu Sep 24 12:19:30 2015 +0300 @@ -1,5 +1,11 @@ package IMPL::Config::Descriptor; +use strict; +use IMPL::Exception(); +sub Activate { + my ($this, $context) = @_; + die IMPL::NotImplementedException->new(); +} 1; diff -r 30e8c6a74937 -r af8d359ee4cc lib/IMPL/Config/Hierarchy.pm --- a/lib/IMPL/Config/Hierarchy.pm Mon Sep 21 19:54:10 2015 +0300 +++ b/lib/IMPL/Config/Hierarchy.pm Thu Sep 24 12:19:30 2015 +0300 @@ -50,16 +50,19 @@ my $cache = $this->{$_cache}{$role}; unless ($cache) { - $cache = {}; + $cache = { $role, 0 }; - my @roles = ($role); - + my @roles = [$role, 0]; + while (my $r = shift @roles ) { - next if $cache->{$r}; - - $cache->{$r} = 1; - if(my $parents = $this->{$roles}{$r}) { - push @roles, @$parents; + my ($name, $level) = @$r; + + $cache->{$name} = $level; + if(my $parents = $this->{$roles}{$name}) { + foreach my $p (@$parents) { + next if $cache{$p}; + push @roles, [$p, $cache{$p} = $level + 1]; + } } } $this->{$_cache}{$role} = $cache;