我有一个我正在使用Net::LDAP
查询的LDAP目录。这给了我一组亲子关系。
这是一个人的目录 - 并包含一个'经理'DN(这是目录中的另一个字段)。
我真的遇到了将此经理 - >人员记录集转换为层次结构的问题。
到目前为止我得到的是:
#!/usr/bin/env perl
use strict;
use warnings;
use Net::LDAP;
use Data::Dumper;
my %people;
my $ldap = Net::LDAP->new('my_ldap_server');
my $result = $ldap->bind('bind_dn');
die if $result->code;
my $search = $ldap->search(
base => 'ou=yaddayadda',
scope => 'subtree',
filter => 'objectClass=person',
attrs => ['manager'],
);
foreach my $found ( $search->entries ) {
my $mgr = $found->get_value('manager');
my $dn = $result->dn;
push( @{ $people{$mgr} }, $dn );
}
这给了我一个经理人和为他们工作的人(使用DN,这是唯一的)。
来自%people
的条目如下:
$VAR1 = {
'cn=Firstname Lastname,ou=OrgUnit' => [
'cn=Personame Lastname,ou=OrgUnit',
'cn=AnotherPerson NameHere,ou=OrgUnit',
],
'cn=AnotherPerson NameHere,ou=OrgUnit' => [
'cn=Someone Else,ou=OrgUnit',
]
};
但我将把父子映射转换为层次结构时遇到了麻烦。
e.g:
'ceo' => [
'pa' => [],
'head_of_dept' => [
'person' => [],
'person_with_staff' => [ 'person3', 'person4' ]
]
]
我对如何实现这一点感到茫然。考虑到每个人在组织结构中都是独一无二的,这似乎不应该太难。
注意 - 在上面,我有cn=AnotherPerson NameHere,ou=OrgUnit
谁有一个下属,我正在制作一个嵌套的映射:
e.g:
$VAR1 = {
'cn=Firstname Lastname,ou=OrgUnit' => [
'cn=Personame Lastname,ou=OrgUnit',
'cn=AnotherPerson NameHere,ou=OrgUnit',
[
'cn=Someone Else,ou=OrgUnit'
]
]
};
答案 0 :(得分:3)
您需要的是有向图,我建议使用Graph::Directed
模块,其方法记录在Graph
这个程序会为你构建图形,但没有任何数据我无法测试它,除了确保它编译
$('#frmInventario').submit(function () {
debugger;
var oTable = $('#TableId').dataTable();
oTable.fnFilter("");
var oSettings = oTable.fnSettings();
oSettings._iDisplayLength = -1;
oTable.fnDraw();
});
生成的use strict;
use warnings 'all';
use feature 'say';
use Net::LDAP;
use Graph::Directed;
use Data::Dumper;
my $ldap = Net::LDAP->new('my_ldap_server');
my $result = $ldap->bind('bind_dn');
die if $result->code;
my $search = $ldap->search(
base => 'ou=yaddayadda',
scope => 'subtree',
filter => 'objectClass=person',
attrs => ['manager'],
);
my $g = Graph::Directed->new;
for my $found ( $search->entries ) {
my $mgr = $found->get_value('manager');
my $dn = $result->dn;
$g->add_edge($mgr, $dn);
}
say $g;
对象具有字符串化重载,因此您可以通过简单地打印它来表面检查它,但是当您想要进一步询问结构时,您需要知道graph theory的一些术语。 。例如,Graph::Directed
将返回所有具有后代但没有父级的节点的列表 - 在这种情况下,是高级管理人员列表,或$g->source_vertices
将返回 true 如果您的数据在任何地方都有任何循环
这是一个程序示例,它使用您的简短示例数据来显示节点的分层树
$g->is_cyclic
use strict;
use warnings 'all';
use Graph::Directed;
my $data = {
'cn=Firstname Lastname,ou=OrgUnit' => [
'cn=Personame Lastname,ou=OrgUnit',
'cn=AnotherPerson NameHere,ou=OrgUnit',
],
'cn=AnotherPerson NameHere,ou=OrgUnit' =>
[ 'cn=Someone Else,ou=OrgUnit', ]
};
my $g = Graph::Directed->new;
for my $mgr ( keys %$data ) {
$g->add_edge($mgr, $_) for @{ $data->{$mgr} };
}
dump_tree($_) for $g->source_vertices;
sub dump_tree {
my ($node, $level) = ( @_, 0);
print ' ' x $level, $node, "\n";
dump_tree($_, $level+1) for $g->successors($node);
}
答案 1 :(得分:2)
@Hunter McMillen unfortunately deleted his very good but slightly off answer。这是我试图通过改变 underling - >之间的关系来增强他的代码。老板走向老板 - >下属
为了模拟LDAP响应,我创建了一个简单的Moose类。
package Person;
use Moose;
has name => ( is => 'ro' );
has boss => ( is => 'ro', predicate => 'has_boss' );
package main;
use strict;
use warnings;
use Data::Printer;
# make a randomized list of people
my %people = map { $_->name => $_ }
map {
Person->new(
name => $_->[0], ( $_->[1] ? ( boss => $_->[1] ) : () )
)
} (
[qw( ceo )], [qw( head_of_dept ceo)],
[qw( person head_of_dept)], [qw( person_with_staff head_of_dept )],
[qw( person3 person_with_staff )], [qw( person4 person_with_staff )],
);
my %manages;
foreach my $p (values %people) {
push @{ $manages{ $p->boss } }, $p->name if $p->has_boss;
}
# this part shamelessly stolen from @HunterMcMillen's deleted answer
sub build_tree {
my ($person) = @_;
my @subtrees;
foreach my $managee ( @{ $manages{$person} } ) {
push @subtrees, build_tree($managee);
}
return { $person => \@subtrees };
}
p build_tree 'ceo';
这是输出。
\ {
ceo [
[0] {
head_of_dept [
[0] {
person []
},
[1] {
person_with_staff [
[0] {
person4 []
},
[1] {
person3 []
}
]
}
]
}
]
}
这应该或多或少是你想要的。