changeset 413:af8d359ee4cc ref20150831

working on di container
author cin
date Thu, 24 Sep 2015 12:19:30 +0300
parents 30e8c6a74937
children ec6f2d389d1e
files lib/IMPL/Config/Bag.pm lib/IMPL/Config/Container.pm lib/IMPL/Config/Descriptor.pm lib/IMPL/Config/Hierarchy.pm
diffstat 4 files changed, 180 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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;
--- 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;
--- 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;