view lib/IMPL/Config/ActivationContext.pm @ 416:cc2cf8c0edc2 ref20150831

sync
author cin
date Thu, 29 Oct 2015 03:50:25 +0300
parents 3d24b10dd0d5
children 3ed0c58e9da3
line wrap: on
line source

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',
		ServiceNotFoundException => 'IMPL::Config::ServiceNotFoundException',
	},
	base => {
		'IMPL::Object' => '@_'
	},
	props => {
		container => PROP_RW,
		_services => PROP_RW,
		_cache    => PROP_RW,
		_stack    => PROP_RW
	}
};

sub CTOR {
	my ( $this, $container ) = @_;

	$this->container($container)
	  or die IMPL::InvalidArgumentException->new('container');
	$this->_cache({});
	$this->_stack([]);
}

sub EnterScope {
	my ( $this, $name, $services ) = @_;

	my $info = { name => $name };

	if ($services) {
		die IMPL::InvalidArgumentException->new(
			services => 'An array is required' )
		  unless isarray($services);

		my $bag = $this->container->serviceCache->{ ref($services) };

		unless ($bag) {
			my $container = $this->container;
			$bag = Bag->new( $this->_services );

			$bag->Register(
				$container->GetLinearRoleHash( $_->{role}, $_->{descriptor} ) )
			  foreach @$services;

			$container->serviceCache->{ ref($services) } = $bag;
		}

		$info->{services} = $this->_services;
		$this->_services($bag);
	}

	push @{$this->_stack}, $info;
}

sub LeaveScope {
	my ($this) = @_;

	my $info = pop @{$this->_stack}
	  or die IMPL::InvalidOperationException->new();

	$this->_services( $info->{services} ) if $info->{services};
}

sub GuardScope {
	my ( $this, $name, $services, $action ) = @_;

	$this->EnterScope( $name, $service );
	eval { $action ($this) if $action; } my $err = $@;
	$this->LeaveScope();
	die $err if $err;
}

sub Resolve {
	my ( $this, $role, %opts ) = @_;
	
	my $d = $this->_services->Reolve($role);
	
	unless($d) {
		die ServiceNotFoundException->new($role) unless $opts{optional};
		return $opts{default};
	} else {
		return $d->Activate($this);
	}
}

sub Clone {
	my ($this) = @_;
	
	my $clone = SELF->new($this->container);
	
	$clone->_
}

1;
__END__

=pod

=head1 NAME

C<IMPL::Config::ActivationContext> - an activation context for the service

=head1 SYNOPSIS

For the internal use only

=head1 MEMBERS

=head2 METHODS

=head3 Resolve($serviceId)

=cut