package org.drools.approver
dialect "mvel"
/*********************************************************
* Calculate the transitive closure for the Departments
*********************************************************/
rule "Create direct department hierarchy"
when
$d : Department( parent != null )
not( DepartmentHierarchy( parent == $d.parent, sub == $d ) )
then
insert( new DepartmentHierarchy( $d, $d, 0 ) );
insert( new DepartmentHierarchy( $d.parent, $d, 1 ) );
end
rule "Create transitive department hierarchy"
when
$dh1 : DepartmentHierarchy( )
$dh2 : DepartmentHierarchy( parent == $dh1.sub )
not( DepartmentHierarchy( parent == $dh1.parent, sub == $dh2.sub ) )
then
insert( new DepartmentHierarchy( $dh1.parent, $dh2.sub, $dh1.distance + $dh2.distance ) );
end
/*********************************************************
* Business Rules
*********************************************************/
rule "1. Define eligible approvers"
@doc( "An eligible approver must be a direct or indirect manager of the Person" )
when
// there is a person
$e : Person( )
// that is either an employee or a manager in department d1
$d1 : Department( employees contains $e || managers contains $e )
// and there is a department d2 in which that employee is not a manager of
$d2 : Department( managers not contains $e )
// and the department d2 is a parent department of the department d1 in the hierarchy
$dh : DepartmentHierarchy( parent == $d2, sub == $d1 )
// and there is a manager on the department d2
$m : Person( this memberOf $d2.managers )
then
// this manager is an eligible approver for the employee
insert( new Approver( $e, $m, $dh.distance ) );
end
rule "2.a. Approver cannot be himself"
@doc( "An approver cannot be the employee himself" )
when
$a : Approver( employee == manager )
then
retract( $a );
end
rule "2.b. Approver cannot be a peer"
@doc( "An approver cannot be a peer of the employee" )
when
$a : Approver()
Department( employees contains $a.employee, employees contains $a.manager ) or
Department( managers contains $a.employee, managers contains $a.manager )
then
retract( $a );
end
rule "3.a. Approver cannot report to the employee"
@doc( "An approver cannot report to the employee" )
when
$a : Approver()
$dh : DepartmentHierarchy()
$d1 : Department( this == $dh.parent, managers contains $a.employee )
$d2 : Department( this == $dh.sub, managers contains $a.manager || employees contains $a.manager )
then
retract( $a );
end
rule "3.b. An approver cannot be the peer to someone who reports to the manager"
@doc( "An approver cannot be the peer to someone who reports to the manager" )
when
// An approver
$a : Approver()
// That is a manager of a department
$d : Department( managers contains $a.manager )
// Cannot have a peer
$p : Person( this memberOf $d.managers, this != $a.manager )
// That reports to the employee in another department
$dh : Department( managers contains $a.employee, employees contains $p )
then
retract( $a );
end
rule "Approvers are the nearest managers"
@doc( "From all eligible approvers, the actual approver is the nearest manager in the hierarchy" )
salience -10
when
$a : Approver()
exists( Approver( employee == $a.employee, distance < $a.distance ) )
then
retract( $a );
end
/*******************************************************
* Define the dataset
*******************************************************/
rule "Setup"
salience 100
then
hilary = new Person( "Hilary" );
john = new Person( "John" );
jane = new Person( "Jane" );
mike = new Person( "Mike" );
kate = new Person( "Kate" );
jessica = new Person( "Jessica" );
janet = new Person( "Janet" );
erica = new Person( "Erica" );
a = new Department( "A", null );
a1 = new Department( "A1", a );
a12 = new Department( "A12", a1 );
a2 = new Department( "A2", a );
a21 = new Department( "A21", a2 );
a22 = new Department( "A22", a2 );
a.managers.add( hilary );
a1.managers.add( john );
a1.managers.add( jane );
a12.managers.add( mike );
a12.employees.add( john );
a12.employees.add( mike );
a2.managers.add( kate );
a21.managers.add( jessica );
a21.employees.add( janet );
a22.managers.add( erica );
a22.employees.add( jane );
insert( hilary );
insert( john );
insert( jane );
insert( mike );
insert( kate );
insert( jessica );
insert( janet );
insert( erica );
insert( a );
insert( a1 );
insert( a12 );
insert( a2 );
insert( a21 );
insert( a22 );
end
/*********************************************************
* Printing the result
*********************************************************/
// in a real application, this would probably be a query instead
// that would be invocated on demand by the application
rule "Print all"
salience -20
when
$a : Approver()
then
end