view lib/IMPL/Config/Hierarchy.pm @ 415:3d24b10dd0d5 ref20150831

working on IMPL::Config::Container
author cin
date Tue, 20 Oct 2015 07:32:55 +0300
parents ec6f2d389d1e
children
line wrap: on
line source

package IMPL::Config::Hierarchy;
use strict;

use IMPL::Exception();
use IMPL::lang qw(:base);
use IMPL::clone;
use IMPL::declare {
	base => {
		'IMPL::Object' => undef
	},
	props => [
		roles  => '*rw',
		_cache => '*rw'
	]
};

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

	if ( is( $roles, SELF ) ) {
		$this->roles( clone( $roles->roles ) );
	}
	elsif ( ishash($roles) ) {
		$this->roles({});
		while(my ($n, $p) = each %$roles) {
			$this->AddRole($n,$p);
		}
	}
	elsif ( isarray($roles) ) {
		$this->roles( { map { $_, undef } @$roles } );
	}
	else {
		$this->roles( {} );
	}
}

sub AddRole {
	my ( $this, $role, $parent ) = @_;

	$parent = isarray($parent) ? $parent : [$parent]
	  if $parent;

	die IMPL::InvalidArgumentException->new('role') unless $role;

	$this->roles->{$role} = $parent;
}

sub GetLinearRoleHash {
	my ( $this, $role ) = @_;

	return [] unless $role;

	my $cache = $this->{$_cache}{$role};

	unless ($cache) {
		$cache = { $role, 1 };

		my @roles = ([$role, 1]);
		
		while (my $r = shift @roles ) {
			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;
	}
	
	return $cache;
}

1;