diff lib/IMPL/Config/ActivationContext.pm @ 422:b0481c071bea ref20150831

IMPL::Config::Container tests, YAMLConfiguration now works and tested
author cin
date Sun, 20 Aug 2017 00:20:41 +0300
parents 7798345304bc
children
line wrap: on
line diff
--- a/lib/IMPL/Config/ActivationContext.pm	Sun Jul 16 22:59:39 2017 +0300
+++ b/lib/IMPL/Config/ActivationContext.pm	Sun Aug 20 00:20:41 2017 +0300
@@ -1,21 +1,23 @@
 package IMPL::Config::ActivationContext;
 
 use IMPL::lang qw(:base);
-use IMPL::Const qw(:prop);
 use IMPL::Exception();
 use IMPL::declare {
     require => {
-        Bag                      => 'IMPL::Config::ServicesBag',
+        Bag                      => 'IMPL::Config::Bag',
         ServiceNotFoundException => 'IMPL::Config::ServiceNotFoundException',
+        Descriptor               => '-IMPL::Config::Descriptor'
     },
     base => {
         'IMPL::Object' => '@_'
     },
     props => [
-        container => PROP_RW,
-        instances => PROP_RW,
-        _services => PROP_RW,
-        _stack    => PROP_RW
+        container => 'rw',
+        owner   => 'rw',
+        instances => 'rw',
+        name      => 'rw',
+        _services => 'rw',
+        _stack    => 'rw'
     ]
 };
 
@@ -24,15 +26,23 @@
 
     $this->container($container)
       or die IMPL::InvalidArgumentException->new('container');
+    $this->owner($container);
     $this->_services( $container->services );
     $this->instances( {} );
     $this->_stack( [] );
 }
 
 sub EnterScope {
-    my ( $this, $name, $services ) = @_;
+    my ( $this, $name, $services, $container ) = @_;
+
+    my $info = { name => $this->name };
 
-    my $info = { name => $name };
+    $this->name($name);
+
+    if ( $container && $this->container != $container ) {
+        $info->{container} = $this->container;
+        $this->container($container);
+    }
 
     if ($services) {
         die IMPL::InvalidArgumentException->new(
@@ -42,12 +52,11 @@
         my $bag = $this->container->serviceCache->{ ref($services) };
 
         unless ($bag) {
-            my $container = $this->container;
             $bag = Bag->new( $this->_services );
+            $bag->tag( $container || $this->container );
 
-            #
-            $bag->Register(
-                $container->GetLinearRoleHash( $_->{role}, $_->{descriptor} ) )
+            $bag->Register( $container->GetLinearRoleHash( $_->{role} ),
+                $_->{descriptor} )
               foreach @$services;
 
             $container->serviceCache->{ ref($services) } = $bag;
@@ -66,30 +75,45 @@
     my $info = pop @{ $this->_stack }
       or die IMPL::InvalidOperationException->new();
 
-    $this->_services( $info->{services} ) if $info->{services};
+    $this->name( $info->{name} );
+    $this->_services( $info->{services} )  if $info->{services};
+    $this->conatiner( $info->{container} ) if $info->{container};
 }
 
 sub Resolve {
     my ( $this, $role, %opts ) = @_;
 
-    my $d = $this->_services->Resolve($role);
+    #change of the container may occur only due resolution of the dependency
+    my ( $d, $bag ) = $this->_services->Resolve($role);
 
     unless ($d) {
-        die ServiceNotFoundException->new($role) unless $opts{optional};
+        die ServiceNotFoundException->new(serviceName => $role) unless $opts{optional};
         return $opts{default};
     }
     else {
-        return $d->Activate($this);
+        $this->EnterScope( $d->GetName(), $d->services(), $bag->tag() );
+        my $instance = $d->Activate($this);
+        $this->LeaveScope();
+        return $instance;
     }
 }
 
+sub Activate {
+    my ( $this, $d ) = @_;
+    $this->EnterScope( $d->GetName(), $d->services() );
+    my $instance = $d->Activate($this);
+    $this->LeaveScope();
+    return $instance;
+}
+
 sub Clone {
     my ($this) = @_;
 
-    my $clone = SELF->new( $this->container );
-
+    my $clone = SELF->new( $this->owner );
+    $clone->name($this->name);
+    $clone->container( $this->container );
     $clone->_services( $this->_services );
-    $clone->instances( { %{ $this->instances } } );
+    $clone->instances( $this->instances );
     $clone->_stack( [ @{ $this->_stack } ] );
 
     return $clone;
@@ -110,8 +134,33 @@
 
 =head1 MEMBERS
 
+=head2 PROPERTIES
+
+=head3 [get] container
+
+Current container for the activation context, this container changes
+during resolution process to match the one in which the resulting
+descriptor were defined. Descriptors can use this property to
+access the cache of theirs container.  
+
+=head3 [get] owner
+
+The container which created this context. Descriptors can use this
+property during theirs activation.
+
+=head3 [get] instances
+
+The activation cache which can be used to store instances during
+single resolution process.
+
 =head2 METHODS
 
-=head3 Resolve($serviceId)
+=head3 Resolve($serviceId): $instance
+
+Activates and returns an instance specified by C<$serviceId>
+
+=head3 Activate($descriptor): $instance
+
+Activates and returns an instance of the services for the specified descriptor/
 
 =cut