Bivio::Auth::Role
# Copyright (c) 1999-2009 bivio Software, Inc. All rights reserved.
# $Id$
package Bivio::Auth::Role;
use strict;
use Bivio::Base 'Type.EnumDelegator';
my($_ROLE_GROUP_RE) = qr{^\*(.*)};
my($_A) = b_use('Type.Array');
my($_CACHE) = b_use('Collection.Attributes')->new;
__PACKAGE__->compile;
sub calculate_expression {
my($proto, $name) = @_;
return defined($name)
? $name =~ $_ROLE_GROUP_RE
? $proto->get_category_role_group($1 || 'all')
: [$proto->from_any($name)]
: [sort {$a->as_int <=> $b->as_int} $proto->get_list];
}
sub get_category_role_group {
my($proto, $which) = @_;
return $_CACHE->get_if_exists_else_put($which => sub {
return $which eq 'all' ? [$proto->get_non_zero_list]
: $_A->sort_unique([_group($proto, $which)]);
});
}
sub get_overlap_count {
return int(shift->get_non_zero_list / 2);
}
sub in_category_role_group {
my($self, $which) = @_;
return grep(
$self->equals($_),
@{$self->get_category_role_group($which)},
) ? 1 : 0;
}
sub is_admin {
return shift->in_category_role_group('all_admins');
}
sub is_continuous {
return 0;
}
sub _group {
my($proto, @which) = @_;
return map(
$_ =~ /[\-\+]/
? _group_math($proto, $_)
: $_ =~ /^[a-z]/
? _group($proto, @{_group_lookup($proto, $_)})
: $proto->from_any($_),
@which,
);
}
sub _group_lookup {
my($proto, $which) = @_;
return $proto->internal_category_role_group_map->{$which}
|| b_die($which, ': unknown category group');
}
sub _group_math {
my($proto, $math) = @_;
my($res) = [];
foreach my $op (split(/(?=[\-\+])/, $math)) {
my($sign, $group) = $op =~ /^([\-\+]?)(.+)/;
$sign ||= '+';
$group = $proto->get_category_role_group($group);
if ($sign eq '+') {
push(@$res, @$group);
next;
}
@$res = grep({
my($r) = $_;
!grep($r->equals($_), @$group);
} @$res);
}
return @$res;
}
1;